Shared Behavior in Objective-C Unit Testing with Specta

Posted by | Development | Leave a reply.

Last Spring, Steve Huey posted about Specta, a light-weight TDD / BDD framework for Objective-C.  I’ve recently been working on a project with Steve using Specta to test out Core Data entities, and found its relatively undocumented behavior sharing feature to be useful.

Image via http://www.flickr.com/photos/futureshape/

Image via http://www.flickr.com/photos/futureshape/

Reusable behavior-based tests allow distinct classes with similar prototypes to share the same test cases without duplicating the test code.  It’s great for testing two or more classes that have a shared protocol, whether formal or informal.  For example:

  • Subclasses of NSManagedObject that all need to test insertion, assigning properties, saving in a context, etc.
  • Data sources that conform to a protocol and all need to test providing data at an index
  • Multiple implementations of a single data structure that all need to test setting and retrieving data by key

Specta provides the methods sharedExamplesFor and itShouldBehaveLike to allow the same set of test cases to be run from multiple specs.

Specta’s shared behavior code

In the following example, three test cases are shared by specs for NSArray and NSOrderedSet. The tests exercise common functionality for any ordered collection:

The sharing utility methods’ first parameter – the shared behavior name string – must match.  The second parameter is a dictionary for passing any inputs from the caller into the shared behavior to customize it for the particular class under testing.

The sharedExamplesFor block supports all the utility functions available in a non-shared set of test cases, like beforeAll, beforeEach, afterEach, afterAll, describe, etc.  Both the each functions in the shared behavior block and the each functions in the calling spec will be run each time a shared test case is run for the calling spec.

Behavior testing in other frameworks

How common are behavior sharing tools are in other test frameworks?

By itself, OCUnit doesn’t appear to offer any support – you might be stuck with writing macros, or perhaps a category on SenTestCase might work.  Alternatively, this blog post on parameterized test cases might help.

Ruby’s RSpec testing tool supports shared test cases through its shared examples and contexts, which pretty closely mirror Specta’s support.  Does Python’s unittest?

In the JavaScript world, Mocha has shared behaviors, as does Jasmine.  I’m not sure about QUnit, but JavaScript is flexible enough that it probably does.