tags:

views:

135

answers:

5

I have a Unit test project for my Application using DUnit framework. This project have a unit surrounded by a $IFDEF to output test-results in a xml file instead of the gui or just command line. XML_OUTPUT define is enabled by switching the Build configuration.

program DelphiCodeToDoc_Tests;

uses
  TestFramework,
  TextTestRunner,
  Sysutils,
  Forms,
  GUITestRunner,
{$IFDEF XML_OUTPUT}
  XmlTestRunner2 in 'DUnit_addon\XmlTestRunner2.pas',
{$ENDIF}
  DCTDSetupTests in 'IntegrationTests\DCTDSetupTests.pas',
  ...

This works perfectly. The issue starts when I'm adding a new unit to this project from the IDE (a new unit with 'File>New>Unit').

The Test project is now :

uses
  TestFramework,
  TextTestRunner,
  Sysutils,
  Forms,
  GUITestRunner,
  DCTDSetupTests in 'IntegrationTests\DCTDSetupTests.pas',
  ...
  MyNewUnit in 'IntegrationTests\MyNewUnit.pas';

As you see, the test XML_OUTPUT has disappeared ... Each time I'm adding a unit, Delphi IDE deletes this test.

Do you know why and how I can avoid it ?

+4  A: 

The DPR's uses list is managed by the IDE. Unfortunately, there's nothing you can do about this. Officially, you're not supposed to put IFDEFs in the middle of the DPR's uses list because it will do stuff like this if you do.

What I'd do is leave the XmlTestRunner2 unit in the project, and put the IFDEFs inside the unit itself so that if you don't have XML_OUTPUT set, it doesn't compile anything.

Mason Wheeler
I don't want to change the unit by adding IFDEFs inside. See it as a 3rd party unit. Your idea is nice, but I don't like it :)
TridenT
+2  A: 

Only code that is actually used is compiled into your application anyway, so normally, it doesn't hurt to have units in the Uses clause that aren't used.

You can see all the code that is linked into your application when you run the program within your IDE. You should see blue dots next to all of the compiled code.

The one caveat is that you should check the initialization section of the units that are of concern. Any code that is in the initialization section is automatically included simply by including the unit because any code in that section is run as soon as the application starts up. You could add your compiler directive inside the initialization section of the unit, if needed, to avoid any initialization code from being linked in and ran.

Marcus Adams
As the `XmlTestRunner2` don't have any initialization code as opposed to unit test files, I can definitely add this listener inside the uses list. It will be linked only if called later, depending on the build configuration. **So Marcus, so solved my issue !** In other situation, I would apply the `proxy unit` method from `gabr`.
TridenT
+5  A: 

You can add a proxy unit to the main program to bypass this problematic behaviour (which many of us consider a bug, not a feature).

program DelphiCodeToDoc_Tests;

uses
  ...
  XMLTestRunnerProxy,  
  ...

and

unit XMLTestRunnerProxy;

interface

{$IFDEF XML_OUTPUT}
uses
  XmlTestRunner2 in 'DUnit_addon\XmlTestRunner2.pas';
{$ENDIF}

implementation

end.
gabr
This is a good idea that I should use sometime.BUT in this case, I will accept the answer from `Marcus Adams`
TridenT
+3  A: 

The stripping occurs any time the IDE has to modify the DPR's USES clause. Using "Save As" to rename a unit will do the same thing.

To work around it I always create my new units externally as an empty text file and then add them to the DPR manually. It's a bit more work initially, but you do end up only including the units if they're necessary. Also note that when this does happen if you're using anything later than Delphi 2005 you can switch to the "History" tab at the bottom of the edit pane and copy the "Local file" contents to get the version prior to when the unit was added and everything else stripped.

And yes, this is a bug. QC#6294 specifically, and it is open, so Embarcadero is aware of the issue.

Craig Peterson
They're aware of the issue, but from what I've seen when it gets brought up on the Embarcadero forums, it appears to be one of those "this is by design and probably won't get fixed, sorry" sort of issues.
Mason Wheeler
I told Mike Rozlog that I think it reflects poorly on the refactoring support and that it makes cross-platform work more difficult, and his response was a bit more positive than that. I'm assuming the more they hear things like that the more likely they are to fix it.
Craig Peterson
thanks for the reply and the QC link. I should have seen it !
TridenT
A: 

Consider having two projects. Once with the optional code, one without. Then build whichever you want, or both. Using project groups, they will work nicely.

mj2008
yes, but I need to synchronize two project files. Even if I don't modify it very often, there will be case where one is not synchronized !
TridenT