blog.vi-kan.net One thought after another

Running FitNesse tests from the command line

image Using FitNesse to write and run test is nice, but sometimes you want to run the tests as part of an automatic build cycle. FitNesse has this possibility, and fit4delphi comes with a testrunner that makes it possible with delphi code as well.

In the fit4delphi package, inside the testrunner folder, you will find a project named DelphiTestRunner.dproj. You can use this project to automatically run a test, or a suite of tests, and store the result as a file. To do his, you have to tell the testrunner where the FitNesse server is running, and which file and in what format the result should be store in. This is done with command line parameters in the given form:

DelphiTestRunner.exe [options] host port page

Host and port must be the same as specified when starting FitNesse. The page parameter is the url for the wiki page you want to test. All subpages of this page will also be tested.

There are multiple options you can specify.

  • -debug This option will print FitNesse protocol actions to the console.
  • -v This option should give a verbose output about test progress to the console, but personally, I can’t make it work…
  • -results file The result of the testrun is saved to a textfile with the given name.
  • -html file The result of the testrun is saved to a html file with the given name.
  • -xml file The result of the testrun is saved to a xml file with the given name. The xml format is given in the userguide.
  • -nopath This option will make FitNesse ignore !path options specified in the wiki pages.
  • -suiteFilter filter Specifying a filter will only run pages with tags matching the filter. You can read more about this in the userguide.

An example of a command line could be some thing like this:

DelphiTestRunner.exe –html results.html localhost 80 MyTestSuite

FitNesse + Delphi –> Fit4Delphi

FitNesseLogoI have been thinking about FitNesse for a couple of weeks now. It seems to be near to perfect for testing the type of code that I’m currently writing. A lot of calculations with a lot of rules, odd cases and exceptions. So I finally started to check it out, to see if it is possible to use FitNesse to test code written in delphi. After some googling, I found a lot of references to the fact that it is possible, but not much on how. There ain’t much references to people actually using it either. I found two projects, though, Fit4Delphi and DelphiFIT. It looks like DelphiFIT has been merged with the Fit4Delphi project, so there is only one solution left for FitNesse with Delphi. If it is any good, one is all you need, though. At first, it’s a bit unclear what components are playing together in FitNesse. There are two main parts of the system, with two different roles. The first part is the one doing the actual testing bit. The second is a development environment in the form of a wiki, made for writing, invoking and maintaining tests.

Get it running

So let see if we can make this work. Fit4Delphi comes with a older version of FitNesse. You can choose to use this version, or you can get a newer version from fitnesse.org. I like new shiny things, so I downloaded a brand new fitnesse.jar. Assuming that java already exists on your computer, fitnesse.jar is all you need to get going. Put it in a folder somewhere, e.g. c: itnesse\, and run

c:itnesse\java -jar fitnesse.jar

Fitnesse will now unpack it self before it starts. If you later want to upgrade to a newer version of FitNesse, you can download a new jar-file and new resources will be extracted next time you start FitNesse. When FitNesse starts, it will tell you what version it is and what port it is running on. It will also tell you a couple of other things, but the port number is what we need right now. The port number defaults to 80, the standard http port. So fire up you webbrowser, and navigate to http://localhost:80, and you will be presented with the default front page for FitNesse. To the left, you have a tree-structure showing what pages exists in the wiki, and to the right you have the content for the current page. In the FitNesse branch of the tree, you can find the user guide for FitNesse amoung all the acceptance tests for FitNesse itself. On the FrontPage, click the edit-button to the left. At the bottom of the page, write the name of your new testsuite, ‘DelphiTests’, or what ever. It need to be a ‘WikiWord’, though. When you save the document, you will see your inserted text together with a ‘[?]’. This means that the wiki sees your wikiword as a title for a page, but can’t find the page itself. When clicking on the questionmark, the wiki will create the page, and let you edit it. So let’s start with a simple table. Fill out the new page with something like the following:

|test table|
|in value|out value?|
|1|2|

After saving, you will see your table nicely formatted. Is there a Test button to the left? If not, click the Properties-button, and choose Test as page type. Now, click the Test-button… Nothing happends, right? FitNesse finds the table and want it to be tested, but can’t find anyone willing to work. It needs to know who to call for the job. It is done by defining the ‘COMMAND_PATERN’ variable. When testing delphi code, we will need  DelphiFitServer.exe to do the work for us, so we give FitNesse the path to this executable. I have copied both DelphiFitServer.exe and fit.bpl to a ‘bin’-folder in my FitNesse-folder. You will find the source in it4delphi itserver\ and it4delphi it.

!define COMMAND_PATTERN {bin\DelphiFitServer.exe -v %p}

The –v parameters tell DelphiFitServer to print out messages, and the %p parameter represents the path where DelphiFitServer should look for fixtures. FitNesse builds this path from classpath-settings in the wiki. Let’s include one in our page:

!path bin\*.bpl

Let’s hit that Test button again and see if there is any progress. This time we get a lot of yellow on our page. While red tells us that a test did not pass, yellow tells us that something went wrong when trying execute the test. As you can see, DelphiFitServer couldn’t find fixture for our table. If you click the ‘Output Captured’ sign in the right corner, you will get some details on the execution. You can see what exe-file was used, and what bpl-files was loaded. We now need to add some testcode on our own.

Writing our first fixture

From the yellow text, we found that we need a class named ‘TestTable’. Acctually, FitNesse is quite flexible when it comes to naming. You can read more about it the documentation, but I will disclose that a class named ‘TTestTable’ should be accepted. So lets create a new delphi package. Add a reference to fit.bpl and the source path for fit4delphi it\source, fit4delphi it\source\exception and fit4delphi\RegExpr. Create a new unit, and define a new class deriving from TColumnFixture. You will need the file ColumnFixture in your uses section for this to compile. You will also need to enable detailed rtti for your class, and register it with a call to RegisterClass:

unit fitTestTable;

interface

uses
  ColumnFixture;

type
  {$M }
  {$METHODINFO ON}
  TTestTable = class(TColumnFixture)
  published
  end;

implementation

uses
  Classes;

{ TTestTable }

initialization
  RegisterClass(TTestTable)

end.

Build the new package, and move it to the bin folder of your FitNesse installation. Run the test again, and you will find that there is now three exceptions instead of one. Progress! This time, it chokes on the column titles. Could not find field: in value. Well, lets add it, then. A published property named InValue of type double should do. Compile… Copy… Test…  One down, two to go. Of course it choked on the next column also. This time we need to add a function named OutValue returning a double.  Let’s fake the implementation for now, and just return 0.

   TTestTable = class(TColumnFixture)
  private
    FInnValue: double;
  published
    property InnValue: double read FInnValue write FInnValue;
    function OutValue: double;
  end;

Now, that got rid of both the remaining exceptions, but leaves us with some ugly red spots. This is actually good though: Our test runs with out problems, but fails. I will leave it up to you to make the test pass. It shouldn’t be to hard, and the reward of green colour should be enough to make you wanna write some real tests.

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.

TDD, Unittesting and Delphi

image Fit for Developing Software: Framework for Integrated Tests by Rick Mugridge; Ward Cunningham

Publisher: Prentice Hall Pub Date: June 29, 2005 Print ISBN–10: 0–321–26934–9 Print ISBN–13: 978–0–321–26934–8

Pages: 384

image The Art of Unit Testing: with Examples in .NET by Roy Osherove

Publisher: Manning Publications Pub Date: June 28, 2009 Print ISBN–10: 1–933988–27–4 Print ISBN–13: 978–1–933988–27–6

Pages: 320

image Test Driven Development: By Example by Kent Beck

Publisher: Addison-Wesley Professional Pub Date: November 08, 2002 Print ISBN–10: 0–321–14653–0 Print ISBN–13: 978–0–321–14653–3

Pages: 240

image xUnit Test Patterns: Refactoring Test Code by Gerard Meszaros

Publisher: Addison-Wesley Professional Pub Date: May 21, 2007 Print ISBN–10: 0–13–149505–4 Print ISBN–13: 978–0–13–149505–0

Pages: 944

Particle-challenge part 2: OK – the math-part is a little bit hard…

Matrix Transformation It’s summer. I’m 500 km from home, and I’m trying to find some time to continue on the particle-challenge.  In the last post, I didn’t decide where to go next; The world, the particles or physics. After some thinking, I found the first one most important, and chose to read a little about how the coordinate system in OpenGL works. It sounds simple enough, but after some coding, I really feel that I need more math skills to get control of this. I have now started to read ‘Beginning Math and Physics for Game Programmers’ to see if I can get the hang of it.

I have started on a camera class, but can’t make it work quite like I want to. There ain’t much functionality in it yet, either.

The camera consist of three vectors: eye position, forward direction and up direction. In theory, the class should make a rotation-matrix from the forward and up vectors, and then translate the matrix by the eye vector.

For now, it uses gluLookAt( ) to do the transformations instead. The reason why is simply that I can’t get the math to work… I’ll have to look at it some more at a later time, but now, I want more particle-fun and less math-hassle.

snapshot of the code is available.