allending/Kiwi — pull request #442 by modocache (2014-02-09 14:45:10+00:00)
Title: Add shared examples.

Shared examples allow developers to reuse a set of describe, context,
and it nodes to test one or more classes. See the functional tests in
`Tests/Shared Examples/KWSharedExampleFunctionalTest.m` for sample
usage.

Addresses issues #175, #138.

- `KWSharedExampleRegistry` is a singleton that maintains a mapping of
shared example names to `KWSharedExample` instances.
- `KWSharedExample` is a data structure composed of a name and context
block.
- `sharedExamplesFor` creates a `KWSharedExample` and registers it.
- `itBehavesLike` looks up the `KWSharedExample` with the given name and
inserts its context block into the current example group.
- `SHARED_EXAMPLES_BEGIN`, `SHARED_EXAMPLES_END` macros are used to
ensure `sharedExamplesFor` are evaluated prior to any examples.
- In order to allow assertion macros like `should` to be compiled outside
of the implementation block of a `KWSpec`--like within `sharedExamplesFor`,
for example--changed macro to reference global state by using
`KWSpec` class method.
- Changed all pragma marks referencing internal/private methods to
`Internal Methods`.
- Removed unused `KWEncodingForVoidMethod` function.

---

Sample usage:

```objc
// CruiserSpecHelpers.m

SHARED_EXAMPLES_BEGIN(CruiserSpecHelpers)

sharedExamplesFor(@"a cruiser", ^(Class describedClass) {
__block Cruiser *cruiser = nil;
beforeEach(^{
cruiser = [[describedClass alloc] initWithCallsign:@"Planet Express"];
});

it(@"has a callsign", ^{
[[cruiser.callsign should] equal:@"Planet Express"];
});
});

SHARED_EXAMPLES_END
```

```objc
// CruiserSpec.m

SPEC_BEGIN(KWSharedExampleFunctionalTest)

describe(@"Cruiser", ^{
itBehavesLike(@"a cruiser", [Cruiser class]);
});

describe(@"Carrier", ^{
itBehavesLike(@"a cruiser", [Carrier class]);
});

SPEC_END
```

---

Feedback very much appreciated! I'm not particularly thrilled with the use of macros--I'd prefer to use @sharplet's `CONFIG_START` and `CONFIG_END` macros, but they don't seem to be working for me.