But, we have DUnit....
Unit Testing in Delphi is not new, the DUnit framework has been around for many years. So why create a new unit test framework? My motivation for creating a new framework was partially frustration with the confusion over DUnit, DUnit2 and who was maintaining DUnit? Sourceforge and subversion makes it very difficult to make contributions to projects. I thought about forking DUnit and putting it up on GitHub or Bitbucket, but my feeling was that would make it even more confusing. Add to that, DUnit was created a long time ago, it's full of IfDefs for CLR, LINUX etc, so it's probably best left alone (I don't have Kylix or Delphi.NET installed).
DUnitX supports Delphi 2010 or later. If you need support for older versions of Delphi, I'm afraid you will have to stick with DUnit, DUnitX makes use of Generics, Attributes and Anonymous methods. D2010 support has some limitations due to compiler bugs.
DUnitX - How does it differ from DUnit?
DUnitX is modeled after NUnit, with some ideas borrowed from xUnit as well. The terminology is different to DUnit, so it's worth looking at the differences below :
Base Test Class |
TTestCase |
None |
Test Method |
Published |
Published or decorated with [Test] |
Fixture Setup Method |
NA |
Decorated with [SetupFixture] or constructor* |
Test Setup Method |
Override Setup from base class |
Decorated with [Setup] |
Test TearDown Method |
Override Teardown from base class |
Decorated with [TearDown] |
Namespaces |
Through registration parameter (string) |
Unit Names (periods delimit namespaces). |
Data driven Tests |
NA |
Decorated with [TestCase(parameters)] |
Asserts |
Check(X) |
Assert class |
Asserts on Containers(IEnumerable) |
Manual |
Assert.Contains*, Assert.DoesNotContain*, Assert.IsEmpty* |
Asserts using Regular Expressions |
NA |
Assert.IsMatch (XE2 or later). |
Stack Trace support |
Jcl |
Jcl, madExcept 3, madExcept 4, Eurekalog 7 ** |
Memory Leak Checking |
FastMM4 |
FastMM4 (under construction) ** |
IoC Container |
Use Spring or other |
Simple IoC container Built in. |
Console Logging |
Built in |
Built in (quiet or verbose modes). |
XML Logging |
Built in (own format) |
Built in - Outputs NUnit compatible xml. |
* Not available in D2010 due to compiler bugs.
** Extensible, simple api.
DUnitX is Attribute driven. Any class can be a Test Fixture. The benefit this brings is to isolate internal architecture changes to the test framework from the tests that use the framework. Logging, stack trace support and memory leak tracking support are extensible and replacable via the built in IoC container and simple interfaces. The XML Logger for DUnitX outputs NUnit compatible XML, which means the xml can be imported by FinalBuilder and Continua CI (which can display the results nicely).
So what does a DUnitX Test look like?
type
uses
DUnitX.TestFramework;
type
[TestFixture('Example','General Example Tests')]
TExampleFixture = class
public
[SetupFixture]
procedure IamAboutToRunSomeTests;
[TeardownFixture]
procedure OKIAmDoneThanks;
[Setup]
procedure SetupMyTestPlease;
[TearDown]
procedure TearDownMyTestPlease;
[Test]
procedure APublicTest;
//Ignored Test will show as ignored in the log.
[Test]
[Ignore('Need to rewrite this test')]
procedure IAmNotReadyToRunYet;
[Test]
[TestCase('Case 1','1,2')]
[TestCase('Case 2','3,4')]
[TestCase('Case 3','5,6')]
procedure RunMeMoreThanOnce(param1 : integer; param2 : integer);
[Test(false)] //Disabled Test. Will not show in the log, will not run
procedure DontCallMe;
published
procedure IAmATest;
end;
Can I convert my DUnit Tests to DUnitX?
DUnitX has limited support for DUnit Tests. Conversion to DUnitX is relatively simple, DUnitX.DUnitCompatibility.pas has a TTestCase class with all the Check(X) methods on it (marked as deprecated, which delegate to the new Assert methods. In the uses clause, replace
TestFramework
with
DUnitX.TestFramework,DUnitX.DUnitCompatibility;
and change the registration to
TDUnitX.RegisterTestFixture(TYourTestClass)
Enabling Stack Trace Support
DUnitX has a DUnitX.StackTrace.inc file, uncomment the define for the provider you want to use. If you want to provide your own stack trace provider, then implement IStacktraceProvider and register it with
TDUnitXIoC.DefaultContainer.RegisterType;
Enabling Memory Leak Tracking
This will be similar to the Stack Trace support when fully implemented.
Where do I get it? Can I contribute?
DUnitX is hosted on GitHub, and we welcome contributions (fork it, make the change and submit a pull request). The project is actively being worked on, with several contributors already. My hope is that someone will help out with MacOS support (we have tried to limit reliance on windows wheree possible). DUnitX is also the test framework being use for the Delphi Unit Test Project (DUT) started by Nick Hodges.