DUnit with FastMM: Detecting memory leaks in individual tests.

  

Steps:

Add the conditional define FASTMM to your project
Ensure you have $(BDS)\source\DUnit\src  in your search path in your project (as otherwise Delphi will pick the pre-built TestFramework.dcu file which was compiled without the FASTMM conditional define)
Inside a test method, or the SetUp method of a class, set FailsOnMemoryLeak to True
If the SetUp method of the class allocates memory, ensure the TearDown de-allocates it. Otherwise you will have leaks:

DUnit will check memory differences from the start of the SetUp until the end of the TearDown
DUnit will not take into account what is freed in the destructor or by automatic finalization after the destructor!

Re-build your application (otherwise the DUnit TestFramework unit will not take into account the FASTMM conditional define)

Depending in your test framework, FailsOnMemoryLeak might be by default be False or True:

TestInsight by default has FailsIfMemoryLeaked set to True for the root test suite (which is then applied to FailsOnMemoryLeak of any test method).

procedure RunRegisteredTests(const baseUrl: string);
var
suite: ITestSuite;
result: TTestResult;
listener: ITestListener;
begin
suite := RegisteredTests;
if not Assigned(suite) then Exit;
result := TTestResult.Create;
result.FailsIfNoChecksExecuted := True;
result.FailsIfMemoryLeaked := True;
listener := TTestInsightListener.Create(baseUrl, suite.CountEnabledTestCases);
result.AddListener(listener);
try
suite.Run(result);
finally
result.Free;
end;
end;

Console DUnit runners (Text, or XML) by default have FailsIfMemoryLeaked set to False.
GUI DUnit runner has FailsIfMemoryLeaked depending on the options:

DUnit source differences
Note that recent Delphi versions (I think XE and up) ship with almost the same sources as https://sourceforge.net/code-snapshots/svn/d/du/dunit/svn/dunit-svn-r44-trunk.zip, with these Embarcadero changes:

all SVN timestamps are based on time zone -0400 instead of +0000:

$Date: 2008-04-24 07:59:47 -0400 (Thu, 24 Apr 2008) $
$Date: 2008-04-24 11:59:47 +0000 (Thu, 24 Apr 2008) $

Embarcadero removed:

all comment lines having TODO in them
all files of types .dof, .cfg, and.wmz
the files NGUITestRunner.nfm and NGUITestRunner.pas
the file /etc/usermap
the directory trees /private and /projects

Embarcadero changed

file /src/versioninfo.res from 9.3.0 to 9.2.1 (which is odd, as all files are from 9.3.0)
unit TextTestRunner to support:

CLR (used last in Delphi 2007)
FailureCount
ErrorCount
IndentLevel
PrefixChars
conditional defines ADDITIONAL_INFO, BASIC_INFO
output of UnitName

unit TestExtensions to support:

CLR (used last in Delphi 2007)
conditional defines ANDROID_FIXME and LINUX
compiler directive LEGACYIFEND

GUITestRunner.dfm to have ResultsView: TListView property Height value 45 instead of 39
the below methods to use ReturnAddress in stead of CallerAddr:

TGUITestCase.FindControl
TGUITestCase.Click
TGUITestCase.EnterKeyInto
TGUITestCase.EnterTextInto
TGUITestCase.Show
TGUITestCase.CheckTabTo overloads
TGUITestCase.CheckFocused overloads
TGUITestCase.CheckEnabled overloads
TGUITestCase.SetFocus overloads
TGUITestCase.CheckVisible overloads

method TGUITestRunner.RunTest

from

class procedure TGUITestRunner.RunTest(test: ITest);
begin
with TGUITestRunner.Create(nil) do
begin
try
suite := test;
ShowModal;
finally
Free;
end;
end;
end;

to

class procedure TGUITestRunner.RunTest(test: ITest);
var
GUI :TGUITestRunner;
begin
Application.CreateForm(TGUITestRunner, GUI);
with GUI do
begin
try
suite := test;
ShowModal;
finally
Free;
end;
end;
end;

unit GUITestRunner:

from

procedure RunTest(test: ITest);
begin
with TGUITestRunner.Create(nil) do
begin
try
Suite := test;
ShowModal;
finally
Free;
end;
end;
end;

to

procedure RunTest(test: ITest);
var
GUI :TGUITestRunner;
begin
Application.CreateForm(TGUITestRunner, GUI);
with GUI do
begin
try
Suite := test;
if Suite <> nil then
ShowModal;
finally
Free;
end;
end;
end;

method TGUITestRunner.SetUp not to set SubItems[0] := ”; when there is no test suite.
method TGUITestRunner.FormCreate to use FormatSettings.TimeSeparator instead of TimeSeparator.

unit TestFramework to support:

HPPEMIT
LEGACYIFEND
CLR and _USE_SYSDEBUG_
AUTOREFCOUNT
NEXTGEN
ANDROID
the RunCountAttribute and RunCount support
a CheckEquals overload for uint64
a CheckNotEquals overload for TCharArray
CheckCircularRef
CompareFloatRelative
NotSameErrorMessage with WideString arguments instead of string
a TestDataDir function
ReturnAddress for older compilers

a new unit DUnitTestRunner
a new Makefile file
a new UnitTests.log file

–jeroen

Comments are closed.