blog.vi-kan.net One thought after another

DUnit: Loading tests from dll’s

I wanted to split all my unittests for a project into separate packages to keep tings nice and clean. DUnit comes with a unit called TestModules.pas which helps you do that.

The unit contains three public methods:

function LoadModuleTests(LibName: string) :ITest;
procedure RegisterModuleTests(LibName: string);
procedure UnloadTestModules;

The LoadModuleTests( )-function, dynamically loads the given library (dll or dtl files), and returns an interface to the tests defined within. RegisterModuleTests( ) does the same, but also calls RegisterTest( ) with the interface from the library.

There is one requirement that the library has to satisfy. It must export a function named ‘Test’ that returns a ITest-interface. Following is a basic project file showing how this can be done:

library OurUnitTests;

uses
  TestFramework;

function Test: ITest;
begin
  result := RegisteredTests;
end;

exports
  Test name 'Test';

end;

The Test( )-function simply returns the result from the RegisteredTests( ) method from the TestFramework-unit. RegisteredTests( ) returns a ITestSuite containing all the test classes registered.

Here’s a samle project file that loads all dll-files from the executables folder, and runs all test through the GUITestRunner:

program RunTests;
uses
  Forms,
  TestFramework,
  GUITestRunner,
  TestModules,
  SysUtils,
  Windows,
  JclFileUtils,
  classes,
  Dialogs
  ;

  {$R *.RES}

procedure LoadTests;
var
  filelist: TStringList;
  str: string;
begin
  filelist := TStringList.Create;
  try
    BuildFileList('*.dll', faAnyFile, filelist);

    for str in filelist do
    begin
      try
        RegisterModuleTests(str)
      except
        on E: Exception do
          ShowMessage(e.Message);
      end;
    end;
  finally
    filelist.free;
  end;
end;

begin
  Application.Initialize;

  LoadTests;
  GUITestRunner.RunRegisteredTests;
  UnloadTestModules;
end.

The BuildFileList( ) method comes from JCL, and simply fills a TStringList with filenames from the given mask. As I said, this is a very basic project, but it shows how to use the TestModules-unit to dynamically load tests. This can easily be expanded to a more flexible solution. You could use command parameters to control what folder should be searched for libraries, or what testrunner should be used, GUI or XML or custom runner.