Joost van der Sluis wrote: >>> If I have several tests defined for a component. The component is >>> created and destroyed in the setup and teardown procedures. And then one >>> test is done. >>> >>> But now, when all tests are performed. I want to run those tests again, >>> but then with one different value for a property of the component. >>> >>> And then once again, with another property change. >>> >>> How can I do that in w nice way? >> The framework as designed in JUnit has no external input. So, the >> simplest way is to write a set of tests in which you use the same setup >> and teardown code and assign the value to a property in the body of the >> test method. > > But then, how can I run those tests more then once? > > Or else I've to add wrappers for all the properties I want to change. > for example 10 tests, running with 20 different settings writing = > 20*10=200 procedures... > >> or you could decide to read the property from a text file, but in this >> case you should always remember to change this value and repeat the >> tests, non practical at all. >> Can you send me an example of your tests for which you need this, maybe >> a concrete case could give me a better idea. > > See the attachment in my mail from 11:40 pm. The tests in TestDBBasics. > I want to run them all with GetNDataset(x).Packetrecords := -1, 1, 5, > 10, 100 > > Btw: what do you think of the tests? Improvements are welcome... Didn't have the time to look at your tests yet, but I've written a small example on how to effectively write parameterized tests in fpcunit, that I'm attaching to this mail. It proves once again that the junit framework design is quite flexible and can be simply adapted to different testing needs. I added a short description and some comments to the code to see how to proceed. Ciao, Dean
unit paramstests;
{$mode objfpc}{$H+} interface uses Classes, SysUtils, fpcunit, testutils, testregistry; type {sometimes the different tests to run have a lot of common functionality and they differ only for the presence of a different parameter, or a different property of the class under test. To remove duplication and unnecessary code there is the possibility to manually build a parameterized test suite, see the following example that can be used as a template. The steps are simple, create a new constructor for the testcase that has the parameters you'll want to pass in the tests (in the following examples the parameters are a string input parameter and an integer parameter to use for the testing of the results). In this constructor you have to call the inherited CreateWithName constructor passing the name of the actual test (in the following code the actual test is the DoTest procedure that performs a simple test of the lenght function for the string passed as parameter to the testcase). The parameters are then stored in some private fileds of the testcase. Then you'll have to construct the test suite manually, see the Suite class function, passing the constructor of the testcase with the wanted parameters. Finally you'll add the constructed test to the test registry using the GetTestRegistry.AddTest function in the initialization section. In this example you'll see that four isolated different tests with the same name (DoTest) will be created. The only drawback is in the fact that in case of failure it's not immediate to see which test went wrong, as the tests have the same name. I suggest to pass some information in the string description of the extended assertequals function as a hint (in the DoTest example below I've inserted the parameter that was passed into the test) The same parameterized testcase could be constructed by loading the parameters from an xml file or from an ini file instead of storing them in the private fields of the testcase. I leave this simple implementation as an exercise for the reader :) { TParameterizedTestCase } TParameterizedTestCase = class(TTestCase) private aParam: string; aOut: integer; public constructor Create(const aParameter: string; aOutput: integer); virtual; overload; class function Suite: TTestSuite; published procedure DoTest; end; implementation { TParameterizedTestCase } constructor TParameterizedTestCase.Create(const aParameter: string; aOutput: integer); begin //create a new DoTest testcase inherited CreateWithName('DoTest'); //store the parameters aParam := aParameter; aOut := aOutput; end; class function TParameterizedTestCase.Suite: TTestSuite; begin //manually create the test suite Result := TTestSuite.Create('TParameterizedTestCase'); Result.AddTest(TParameterizedTestCase.Create('', 0)); Result.AddTest(TParameterizedTestCase.Create('o', 1)); Result.AddTest(TParameterizedTestCase.Create('two', 3)); Result.AddTest(TParameterizedTestCase.Create('three', 5)); end; procedure TParameterizedTestCase.DoTest; begin //insert here the common functionality of the parameterized test //here for example we are testing the Length function: AssertEquals('test ' + aParam, aOut, length(aParam)); // notice that the 'test ' + aParam description was added to be able to //distinguish which test went wrong end; initialization //register the manually created suite GetTestRegistry.AddTest(TParameterizedTestCase.Suite); end.