Shared Behavior in Objective-C Unit Testing with Specta
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.
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
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
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.
sharedExamplesFor block supports all the utility functions available in a non-shared set of test cases, like
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?