A.1 Example 1: Create a Book

     

The first example creates the class Book . En route, the unit test framework is built and the first unit test written.

A.1.1 Step 0: Set Up the Unit Test Framework

The framework initially is built on a single class, UnitTest , shown in Figure A-1. The source code for UnitTest includes a header file, UnitTest.h , and an implementation file, UnitTest.cpp , as shown in Example A-1.

Figure A-1. The class UnitTest
figs/utf_aa01.gif

Example A-1. The class UnitTest
 UnitTest.h #define UT_ASSERT( condition ) \         assertTrue(condition,__FILE__,__LINE_  _,#condition) class  UnitTest  {  public:    virtual ~UnitTest( ) {}    virtual void  runTest  ( ) = 0;  protected:    void  assertTrue  (bool condition, const char *file,                    int line, const char *msg);    static int  num_test_success  ; }; UnitTest.cpp #include <stdio.h> #include <stdlib.h> #include "UnitTest.h" int UnitTest::  num_test_success  = 0; void UnitTest::  assertTrue  (bool condition,                             const char *file, int line,                             const char *msg) {    if (!(condition)) {       printf("FAILURE!\n");       printf("%s:%d:%s\n", file, line, msg);       exit(1);    }    ++num_test_success;  } 

UnitTest is an abstract class because it contains the pure virtual function runTest( ) . Actual unit tests will be inherited from UnitTest and must override the runTest( ) method. The function assertTrue( ) should be used to test Boolean conditions in runTest( ) . If the condition is TRUE , the counter num_test_success is incremented. If it is FALSE , the function test_failure() is called. This function reports the file location of the failure and exits. The macro UT_ASSERT() is used in place of direct calls to assertTrue( ) . It uses the preprocessor directives __FILE_ _ and __LINE_ _ to fill in the location of the call at compilation, and the #condition argument allows the conditional expression to be printed in the failure report.

Compile UnitTest with the command g++ -c UnitTest.cpp (or your compiler's equivalent command).

A.1.2 Step 1: Create a Unit Test

Start by creating the unit test class BookTest , as shown in Example A-2.

Example A-2. The definition of the class BookTest
 BookTest.h #include "UnitTest.h" #include "Book.h" class  BookTest  : public  UnitTest  {  public:    void  runTest  ( ) {       Book book("Cosmos");       UT_ASSERT(!strcmp(book.title, "Cosmos"));    } }; 

The unit test BookTest constructs an instance of the class Book , passing the title as an argument, and then tests the value of the book's title attribute. Since the entire implementation of BookTest is present in BookTest.h , no .cpp file is necessary.

BookTest is instantiated and run by a class called TestRunner , which also contains the main( ) method for the test framework. Example A-3 shows the implementation of TestRunner .

Example A-3. The class TestRunner
 TestRunner.cpp #include "stdio.h" #include "BookTest.h" int  main  ( ) {    BookTest test;    test.runTest( );    printf("SUCCESS!\n");    return 0; } 

Compile TestRunner . The compiler will report that it cannot find the file Book.h , and that the class Book is undeclared. No surprise there! So, the next step is to create the most basic implementation of the class Book that will allow the code to compile, as shown in Example A-4.

Example A-4. Initial version of the class Book
 Book.h #include "string.h" class  Book  {  public:    Book(const char* title) {}    char title[255]; }; 

The class TestRunner should compile now. The test framework and the unit test are in place. To run the test, link the objects together into an executable:

 g++ -o TestRunner TestRunner.o UnitTest.o 

Execute TestRunner . The following result is reported :

 FAILURE! BookTest.h:9:!strcmp(book.title, "Cosmos") 

This failure demonstrates that the unit test framework is working. Note how the UT_ASSERT() macro captures the file's name and location, as well as the code contents of the test assertion.

A.1.3 Step 2: Create a Book

BookTest fails because Book does not yet contain the functionality being tested . In this step, the minimum necessary code to achieve unit test success is added.

The constructor for Book is changed to set the title attribute, as shown in Example A-5.

Example A-5. The class Book with title attribute set by the constructor
 Book.h #include "string.h" class Book {  public:    Book(const char* title) {       strcpy(this->title, title);    }    char title[255]; }; 

A.1.4 Step 3: Test Again

The final step is to rebuild the code, re-run the unit test, and see whether the changes produce the desired results.

Rebuild and execute TestRunner . The results of BookTest are reported:

 SUCCESS! 

An instance of Book can now be created and given a title.



Unit Test Frameworks
Unit Test Frameworks
ISBN: 0596006896
EAN: 2147483647
Year: 2006
Pages: 146
Authors: Paul Hamill

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net