Site hosted by Angelfire.com: Build your free website today!

AutoTest - Unit testing framework

Supporting tool for test-first design technique

 

Content

AutoTest - Unit testing framework. 1

Introduction. 1

SetUp. 2

How to use it 2

Specifying test cases. 2

Compiling test cases. 2

Reporting data for diagnostic failing test cases. 3

Choosing windows-based test runner 4

Making the test cases pass. 6

Setting up and Shutting down test suites. 7

Grouping test cases. 8

Once and only once. 9

And now…... 11

Some links. 11

 

 

Introduction

This tool is plain and small, as I designed to be.

The reason behind the design is to put emphasis on the software being designed with the tool, not the tool itself. That is, the tool automates some repetitive tasks and leaves room for what the humans do best, think.

The tool does some tedious tasks for the software designer, but by no means has the tool tried to easy the thinking process of crafting a design.

In the words of Professor Edsger Wybe Dijkstra:

“…tools have the unfortunate tendency to backfire (Easing the correction of errors immediately leads to more errors being made)”

Can computing science save the computer industry?, Edsger W. Dijkstra

http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD920.PDF

 

SetUp

Just copy AutoTest.dll to one of the following locations:

·         Your working folder

·         A subfolder named AutoTest within your working folder

 

How to use it

Specifying test cases

The simplistic case: If you are designing a simple calculator class, convey your usage intentions starting as the following:

CalcTest.cs

class CalcTest : AutoTestSuite

{

      public void testSimpleAdd()

      {

            Calc calc = new Calc();

            Assert( calc.Add(4,3) == 7 );

      }

}

AutoTest will execute all the public methods of CalcTest class which first characters are “test”, each such a method is a test case. AutoTest will report results of executing each test case.

 

Compiling test cases

Compiling CalcTest.cs now will result with several errors about not knowing AutoTestSuite class type, Calc class type and missing entry point for program. Let’s do the simplest thing that make these errors disappear:

using mdmartin.AutoTest; // here is defined AutoTestSuite class type

 

// here is the simplest code that make to compiling errors disappear:

class Calc

{

      public int Add(int n1, int n2)

      {

            return 0;

      }

}

 

// a meaningful program entry point

      static void Main()

      {

            TestSuite suite=new TestSuite("Calc tests");

            suite.Add(new CalcTest());

 

            TestRunner runner = new TextConsoleTestRunner(Console.Out);

            runner.Run(suite);

      }

Let’s compiling again:

            csc /r:AutoTest.dll CalcTest.cs

Execution reports the following:

 

Reporting data for diagnostic failing test cases

Often, we want more information about the failing test case, that information could be specified in the test case:

      public void testSimpleAdd()

      {

            Calc calc = new Calc();

            Assert( calc.Add(4,3) == 7 ,"Simple sum: 4+3 != 7");

      }

Now execution reports:

 

Choosing windows-based test runner

By now, we have been using a test runner for console mode, if we want our test runner on windows mode, then we need to change the line:

            TestRunner runner = new TextConsoleTestRunner(Console.Out);

With this line:

            TestRunner runner = new WinFormTestRunner();

Now, the execution shows the following window:

Selecting the root in the tree view control and clicking on Run button will execute our test cases and report results:

 

Making the test cases pass

A red box tells us that our current detailed design (source code) is not fulfilling our usage intentions of Calc class type, let’s fix that:

class Calc

{

      public int Add(int n1, int n2)

      {

            return n1+n2;

      }

}

Let’s go back to our console mode test runner and see execution results:

Ok, 100% test cases passed! This means our detailed design (source code) fulfill the functional requirements (by now) of our Calc class type.

 

Setting up and Shutting down test suites

Our sample testSimpleAdd test case method above creates an instance of Calc class type for exercising the projected functionality, as the test case methods on this test class grow in number, will be annoying to create instances within each test case method. It may be handy to locate a single point to setting up the instances for all test case methods to use, and another single point to release the resources used by the test case methods.

There are a couple of methods from base class AutoTestSuite that can be overridden for such a purpose, like this:

class CalcTest : AutoTestSuite

{

      private Calc itsCalc;

      public override void SetUp()

      {

            itsCalc = new Calc();

      }

      public override void ShutDown()

      {

            itsCalc = null; // not imperative for memory usage, imperative for other system resources

      }

      public void testSimpleAdd()

      {

            Assert( itsCalc.Add(4,3) == 7 ,"Simple sum: 4+3 != 7");

      }

}

SetUp and ShutDown methods will be executed once each for the entire AutoTestSuite-derived class type, at the beginning and at the end respectively. That is, each test case method is able to use the instance itsCalc, without creating or destroying an instance per test case method.

 

Grouping test cases

As development team members work on different functions of the software being designed, they can group their test cases, making up a hierarchy of test cases as deep and broad as they choose.

For example:

class ScientificCalc : AutoTestSuite

{

      public void testSimpleFourierTransform()

      {

            // test case code for Calc scientific functions

      }

      public void testSymbolicEvaluation() {}

}

 

class MatrixCalc : AutoTestSuite

{

      public void testMatrixAdd() {}

      public void testMatrixDivision() {}

      public void testMatrixMultiplication() {}

}

Setting the test case hierarchy as:

class exe

{

      static TestSuite advancedTest()

      {

            TestSuite suite=new TestSuite("Calc advanced tests");

            suite.Add(new ScientificCalc());

            suite.Add(new MatrixCalc());

            return suite;

      }

      static void Main()

      {

            TestSuite suite=new TestSuite("Calc tests");

            suite.Add(new CalcTest());

            suite.Add(advancedTest());

 

            TestRunner runner = new WinFormTestRunner();

            runner.Run(suite);

      }

}

Using the WinFormTestRunner looks like:

 

Once and only once

If there are AutoTestSuite-derived class types defined in your testing assembly, certainly you want them to be executed; if the test case hierarchy configuration is conveyed by static methods like advancedTest above, then it may be handy to say that kind of decisions in just one place and saying something like “setup test case hierarchy from class types defined in calling assembly”; avoiding to configure the hierarchy at the program entry point.

If this is the case, then you may use the static method SuiteFromCallingAssembly from AutoTestSuite class type like this:

class exe

{

      static void Main()

      {

            TestRunner runner = new WinFormTestRunner();

            runner.Run(AutoTestSuite.SuiteFromCallingAssembly());

      }

}

All the AutoTestSuite-derived class types will be included in your test case hierarchy. For grouping define a TestSuite-derived class type that group the test suites as needed in a TestSuite instance which must be returned from a public static ‘Suite’ method, like the following:

class AdvancedTest : TestSuite

{

      public static TestSuite Suite()

      {

            TestSuite suite=new TestSuite("Calc advanced tests");

            suite.Add(new ScientificCalc());

            suite.Add(new MatrixCalc());

            return suite;

      }

}

Now, the execution inspects the calling assembly and configures the test case hierarchy from the class types defined within.

 

And now…

Just as Mr. Churchill said: “…this is not the end, this is not even the beginning of the end…; perhaps this is the end of the beginning”

It is up to you; give an honorable try to test-first design techniques using supporting tools like this one. It could make a big difference in the quality of your software designs.

 

Some links

Several unit testing frameworks designs http://www.xprogramming.com/software.htm

Code Complete http://www.stevemcconnell.com/cc.htm

Is design dead? http://martinfowler.com/articles/designDead.html

Continuous Integration http://martinfowler.com/articles/continuousIntegration.html

Avoiding Repetition http://martinfowler.com/articles/repetition.pdf

 

Best regards,

Marco A. Dorantes