SourceForge.net Logo
TestKit Documentation
 
 
Fixtures
It's quite common to want to write many tests against an object with a common state. To avoid having to write something like:
@implementation MyTest

-( void ) testOne
{
    MyClass *myObj = [ self buildMyObj ];
    //test
    [ myObj release ];
}

-( void ) testTwo
{
    MyClass *myObj = [ self buildMyObj ];
    //test
    [ myObj release ];
}

@end
                            
you can take advantage of a fixture. In TestKit, a fixture is an instance of a subclass of TWTestCase. Note that the instance itself is the fixture, while each instance method is considered a test case. To create a fixture, subclass TWTestCase and declare instance variables for the object you'll be running your tests against:
#import <TestKit/TestKit.h>

@class MyClass;

@interface MyTest:TWTestCase
{
    MyClass *myObj;
}

@end
                            
In your implementation, override -[ TWTestCase setup ] and -[ TWTestCase teardown ] .
#import "MyTest.h"

@implementation MyTest

-( void ) setup
{
    myObj = [ [ MyClass alloc ] init ];
    //perform other setup to myObj
}

-( void ) teardown
{
    [ myObj release ];
}

-( void ) testFoo
{
    //test against myObj
}

-( void ) testBar
{
    //test against myObj
}

@end
                            
Before any test is run, setup is called. After a test completes, regardless of whether or not it succeeds, teardown is called.

Note:
setup and teardown are highly preferred over init and dealloc. The former pair is called before and after each test, while the latter pair is called on object instantiation and release. This is significant because TestKit will create an instance of a fixture for every test method on that fixture. These instances are created when the test bundle is loaded, and before any tests are run. None of those objects are released until either the application exits, or another set of tests are chosen.

By contrast, only one test is executed at a time. setup is called immediately before the test is run, and teardown is called immediately after. If the objects you are testing are resource intensive, or if they obtain exclusive rights to resources, you will not have much success initializing your instance variables through init.

Using the example above to illustrate:

Suppose instances of MyClass obtain exclusive rights to a file or port. When TestRunner loads the test bundle, 2 instances of MyTest will be created. One for the test case testFoo, and the other one for testBar. If you chose to initialize myObject in init instead of setup, 2 instances of MyClass will try to be instantiated. The first will succeed. The second instance will crash, block indefinitely, or fail - even before a single test has run.

If you chose, however, to initialize myObj in the setup method, no instances of MyClass will be instantiated until before testFoo or testBar are run. Since only one test is run at a time, only one instance of MyClass will be instantiated at a time.