Description Create a test fixture capabile of running a single testcase. The test case that will be run is the method called MethodName, which must be declared in the published section of a sub-class of TTestCase.
procedure TAbstractTest.LoadConfiguration(const fileName: string);
var
f :TIniFile;
begin
f := TIniFile.Create(fileName);
try
LoadConfiguration(f, 'Tests')
finally
f.free
endEnd;
Description Run will Create a TTestResult, run this test case and collect any TTestFailure into the TTestResult. The caller is responsible for freeing the returned TTestResult.
Returns A TTestResult with the results of running this test.
Implementation
function TAbstractTest.Run: TTestResult;
var
testResult : TTestResult;
begin
testResult := TTestResult.Create;
try
testResult.RunSuite(self);
except
testResult.Free;
raise;
end;
Result := testResult;
End;
procedure TAbstractTest.SaveConfiguration(const fileName: string);
var
f :TIniFile;
begin
f := TIniFile.Create(fileName);
try
SaveConfiguration(f, 'Tests')
finally
f.free
endEnd;
Description This class is used by the framework to make the creation of test suites easy. Users of the framework should never have to use this class directly
constructor TMethodEnumerator.Create(AClass: TClass);
type
TMethodTable = packedrecord
count: SmallInt;
//[...methods...]
end;
var
table: ^TMethodTable;
name : ^ShortString;
i, j : Integer;
begininherited Create;
while aclass <> nildobegin
// *** HACK ALERT *** !!!
// Review System.MethodName to grok how this method works
asm
mov EAX, [aclass]
mov EAX,[EAX].vmtMethodTable { fetch pointer to method table }
mov [table], EAX
end;
if table <> nilthenbeginname := Pointer(PChar(table) + 8);
for i := 1 to table.count dobegin
// check if we've seen the method name
j := Low(FMethodNameList);
while (j <= High(FMethodNameList))
and (name^ <> FMethodNameList[j]) do
inc(j);
// if we've seen the name, then the method has probably been overridden
if j <= High(FMethodNameList) then
CONTINUE;
SetLength(FMethodNameList,length(FMethodNameList)+1);
FMethodNameList[j] := name^;
name := Pointer(PChar(name) + length(name^) + 7)
end;
end;
aclass := aclass.ClassParent;
end;
End;
Description To define a test case 1) implement a subclass of TestCase 2) define instance variables that store the state of the fixture 3) initialize the fixture state by overriding setUp 4) clean-up after a test by overriding tearDown. Each test runs in its own fixture so there can be no side effects among test runs. Here is an example:
For each test implement a method which interacts with the fixture. Verify the expected results with tests specified by calling check with a boolean and an optional message.
procedure TMathTest.testAdd;
var
testResult: Float;
begin
testResult := fValue1 + fValue2;
check(testResult = 5.0);
end;
Description Create a test fixture capabile of running a single testcase. The test case that will be run is the method called MethodName, which must be declared in the published section of a sub-class of TTestCase. see @TTestSuite see @ITestSuite
Declaration Function EqualsErrorMessage(expected, actual, msg: string): string;
Implementation
function TTestCase.EqualsErrorMessage(expected, actual :string; msg :string) :string;
beginif (msg <> '') then
msg := msg + ', ';
Result := Format('%s expected and actual were:<%s>', [msg, expected])
End;
Description Performs the test. The pre-conditions for the test must already have been met. runTest may leave the system in an unknown state. Do not override this function to Create testcases.
Description This method is used to ensure that state of the application is in a known state before running any test cases. This method is called before each test is executed in this TTestCase. Override this method to add code to setup the preconditions for the testcases declared in descendants of TTestCase.
Description TTestCase descendants do not need to manipulate TTestFailures directly. TTestFailures are used by TTestResult to keep track of the results of running a set of tests. TTestFailure is used by the test runners to report test failures. see TTestResult
Description Constructs a TTestFailure with the given test and the exception which occurred while running that test. see TTestResult.AddError see TTestResult.AddFailure
Description It is an instance of the Collecting Parameter pattern. The test framework distinguishes between failures and errors. A failure is anticipated and checked for with checks. Errors are unanticipated problems that raise an exception. see Check see ITest
Description Creates a TTestFailure recording that an error occurred in test. Notifies any registered ITestListeners that an error occurred. The TTestFailure returned should not be freed.
Parameters
test
The test with an error.
e
The exception that caused the error.
Returns the TTestFailure object representing this error.
Implementation
function TTestResult.AddError(test: ITest; e: Exception; msg :string): TTestFailure;
var
i: integer;
error : TTestFailure;
begin
assert(assigned(test));
assert(assigned(e));
assert(assigned(fErrors));
error := TTestFailure.Create(test, e, msg);
fErrors.add(error);
for i := 0 to fListeners.count - 1 dobegin
(fListeners[i] asITestListener).AddError(error);
end;
assert(assigned(error));
Result := error;
End;
Declaration Function AddFailure(test: ITest; e: Exception): TTestFailure;
Description Creates a TTestFailure recording that a failure occurred in test. Notifies any registered ITestListeners that a failure occurred. The TTestFailure returned should not be freed.
Parameters
test
The test that failed.
e
The exception that caused the failure.
Returns The TTestFailure object representing this failure.
Implementation
function TTestResult.AddFailure(test: ITest; e: Exception): TTestFailure;
var
i: integer;
Failure : TTestFailure;
begin
assert(assigned(test));
assert(assigned(e));
assert(assigned(fFailures));
Failure := TTestFailure.Create(test, e);
fFailures.add(Failure);
for i := 0 to fListeners.count - 1 dobegin
(fListeners[i] asITestListener).AddFailure(Failure);
end;
assert(assigned(Failure));
Result := Failure;
End;
destructor TTestResult.destroy;
var
i: Integer;
begin
fListeners := nil;
for i := 0 to fErrors.Count - 1 dobegin
TTestFailure(fErrors[i]).Free;
end;
fErrors.Free;
for i := 0 to fFailures.Count - 1 dobegin
TTestFailure(fFailures[i]).Free;
end;
fFailures.Free;
inherited Destroy;
End;
Description Notify any registered ITestListener that a test was completed.
Implementation
procedure TTestResult.EndTest(test: TTestCase);
var
i: integer;
begin
assert(assigned(fListeners));
for i := 0 to fListeners.count - 1 dobegin
(fListeners[i] asITestListener).EndTest(test);
end;
End;
Description Run executes a test cases and broadcasts status informatio to any listeners registered with this TTestResult. Run also records any failures or errors that occur while running the testcase.
Implementation
procedure TTestResult.Run(test: TTestCase);
begin
assert(assigned(test));
if ShouldStop then
EXIT;
StartTest(test);
trytry
test.SetUp;
except
on e: Exception dobegin
AddError(test, e, 'SetUp FAILED: ');
EXIT;
endend;
try
test.RunTest;
except
on e: EStopTestsFailuredobegin
AddFailure(test, e);
FStop := True;
end;
on e: ETestFailuredobegin
AddFailure(test, e);
end;
on e: EBreakingTestFailuredobegin
AddFailure(test, e);
end;
on e: Exception dobegin
AddError(test, e);
end;
end;
try
test.TearDown;
except
on e: Exception do
AddError(test, e, 'TearDown FAILED: ');
end;
finally
EndTest(test);
end;
End;
Description Run executes a test cases and broadcasts status informatio to any listeners registered with this TTestResult. Run also records any failures or errors that occur while running the testcase. Listeners are also notified when TestingStarts and ends.
Parameters
test
The test case to run.
Implementation
procedure TTestResult.RunSuite(test: TAbstractTest);
begin
TestingStarts;
try
test.RunBare(self);
finally
TestingEnds
endEnd;
Description Notify any registered ITestListener that a test was started.
Implementation
procedure TTestResult.StartTest(test: TTestCase);
var
i: integer;
begin
assert(assigned(test));
assert(assigned(fListeners));
inc(fRunTests);
for i := 0 to fListeners.count - 1 dobegin
(fListeners[i] asITestListener).StartTest(test);
end;
End;
procedure TTestResult.TestingEnds;
var
i :Integer;
beginfor i := 0 to fListeners.count - 1 dobegin
(fListeners[i] asITestListener).TestingEnds(self);
end;
End;
procedure TTestResult.TestingStarts;
var
i :Integer;
beginfor i := 0 to fListeners.count - 1 dobegin
(fListeners[i] asITestListener).TestingStarts;
end;
End;
Description It runs a collection of test cases. It should not be necessary for test writers to extend TTestSuite. Decorators should be used instead. see TTestDecorator. see RegisterTest see ITest
procedure TTestSuite.AddTests(testClass: TTestCaseClass);
var
MethodIter : Integer;
NameOfMethod : string;
MethodEnumerator : TMethodEnumerator;
begin
{ call on the method enumerator to get the names of the test
cases in the testClass }
MethodEnumerator := nil;
try
MethodEnumerator := TMethodEnumerator.Create(testClass);
{ make sure we add each test case to the list of tests }
for MethodIter := 0 to MethodEnumerator.Methodcount-1 dobegin
NameOfMethod := MethodEnumerator.nameOfMethod[MethodIter];
self.addTest(testClass.Create(NameOfMethod) asITest);
end;
finally
MethodEnumerator.free;
end;
End;
Declaration Function CountEnabledTestCases: integer;
Returns The number of enabled test cases.
Implementation
function TTestSuite.CountEnabledTestCases: integer;
var
i: Integer;
test: ITest;
Total : Integer;
begin
assert(assigned(fTests));
Total := 0;
if getEnabled thenbeginfor i := 0 to fTests.Count - 1 dobegin
test := fTests[i] asITest;
Total := Total + test.CountEnabledTestCases;
end;
end;
Result := Total;
End;
function TTestSuite.CountTestCases: integer;
var
test: ITest;
i: Integer;
Total : integer;
begin
assert(assigned(fTests));
Total := 0;
for i := 0 to fTests.Count - 1 dobegin
test := fTests[i] asITest;
Total := Total + test.CountTestCases;
end;
Result := Total;
End;
procedure TTestSuite.RunBare(testResult: TTestResult);
var
i: Integer;
test: ITest;
begin
assert(assigned(testResult));
assert(assigned(fTests));
if getEnabled thenbeginfor i := 0 to fTests.Count - 1 dobeginif testResult.ShouldStop then
BREAK;
test := fTests[i] asITest;
test.RunBare(testResult);
end;
end;
End;
Description Run will Create a TTestResult, run this test case and collect any TTestFailure into the TTestResult. The caller is responsible for freeing the returned TTestResult.
Returns A TTestResult with the results of running this test.
Description TTestResult calls the methods of registered ITestListeners as testing progress. The standard TestRunners implement this interface to receive notifications about testing events.
Declaration Function MakeTestSuites(name :string; const classes :arrayofTTestCaseClass): ITestSuite;
Parameters
name
The name the ITestSuite will have.
classes
The series of TTestCase classes that will compose the suite.
See Also
Create
Suite
Use TTestCase.Create(string, array of ITest) instead
Implementation
function MakeTestSuites(name :string; const classes :arrayofTTestCaseClass): ITestSuite;
var
i :Integer;
begin
result := TTestSuite.Create(name);
for i := Low(classes) to High(classes) dobegin
result.addTest(testSuiteOf(classes[i]));
end;
End;
Description Add a test to an arbitraty test suite in the test hierarchy. The SuitePath is a dot-separated list of suite names. The first name is taken to be a top level suite, the second a child of the first, and so on. Test suites are created if they don't exist. The test is added to the suite indicated by the last names.
Parameters
SuitePath
Dot separated list of test suite names, indicating a path from the root of the test hierarchy. Tests are added to the suite indicated by the last name.
Indicates a path of tests suites to register the test under.
Tests
The series of tests to register.
Implementation
procedure RegisterTests(SuitePath :string; const Tests :arrayofITest);
var
i :Integer;
beginfor i := Low(Tests) to High(Tests) dobegin
TestFramework.RegisterTest(SuitePath, Tests[i])
endEnd;
Indicates a path of tests suites to register the test under.
Tests
The series of tests to register.
See Also
Suite
Create
Use RegisterTest(string, array of ITest) instead, in combination with TTestCase.Suite, and TTestSuite.Create.
Implementation
procedure RegisterTestSuites(SuitePath :string; const classes :arrayofTTestCaseClass);
var
i :Integer;
beginfor i := Low(classes) to High(classes) dobegin
TestFramework.RegisterTest(SuitePath, classes[i])
endEnd;
function RunTest(suite :ITest; listeners :arrayofITestListener) :TTestResult; overload;
var
i :Integer;
begin
result := TTestResult.Create;
for i := low(listeners) to high(listeners) do
result.addListener(listeners[i]);
suite.Run(result);
End;
Description When set to True, the framework raises EEBreakingTestFailure when a test fails. The Delphi IDE will break on this type of exception by default. When set to False, the framework will raise ETestFailure instead, which is derived from EAbort, and on which the IDE will not brak by default. The default value is False.
Parameters
Enable
True means enable IDE breaking on failure exceptions.