Reputation: 19331
I have a few repetitive specs that I would like to DRY up. The common functionality doesn't lend itself to moving into a beforeEach
block. Essentially, it's object creation and is 4 lines for each of 12 objects, I'd like to turn those 4 lines into a single function call.
Where can I put helper functions in a Kiwi spec?
In RSpec I can just put def
between spec blocks, but that doesn't appear to be possible here. I've even tried skipping the SPEC_END
macro and adding that content myself so I could add functions inside the @implementation from SPEC_BEGIN
but that doesn't seem to work, either.
Correction... I can manage something that kind of works with hand-coding the SPEC_END
macro. I had the end } mis-placed. But still, it fails, because the method isn't in the @interface
.
Upvotes: 14
Views: 2838
Reputation: 38106
supermarin suggests the following method:
@implementation KWSpec(Additions)
+ (void)myHelperMethod:(Car*)car {
[[car shouldNot] beNil];
};
@end
SPEC_BEGIN(FooBarSpec)
describe(@"A newly manufactured car", ^{
it(@"should not be nil", ^{
[self myHelperMethod:[CarFactory makeNewCar]];
});
});
SPEC_END
Another option is as Doug suggests:
SPEC_BEGIN(FooBarSpec)
void (^myHelperMethod)(Car*) = ^(Car* car){
[[car shouldNot] beNil];
};
describe(@"A newly manufactured car", ^{
it(@"should not be nil", ^{
myHelperMethod([CarFactory makeNewCar]);
});
});
SPEC_END
The nice thing about it is that it lends itself nicely to async scenarios:
SPEC_BEGIN(FooBarSpec)
__block BOOL updated = NO;
void (^myHelperAsync)() = ^()
{
[[expectFutureValue(theValue(updated)) shouldEventually] beYes];
};
describe(@"The updater", ^{
it(@"should eventually update", ^{
[[NSNotificationCenter defaultCenter] addObserverForName:"updated"
object:nil
queue:nil
usingBlock:^(NSNotification *notification)
{
updated = YES;
}];
[Updater startUpdating];
myHelperAsync();
});
});
SPEC_END
Finally, if your helper method resides in another class, gantaa suggests a clever hack:
@interface MyHelperClass
+(void)externalHelperMethod:(id)testCase forCar:(Car*)car
{
void (^externalHelperMethodBlock)() = ^(){
id self = testCase; //needed for Kiwi expectations to work
[[car shouldNot] beNil];
};
externalHelperMethodBlock();
}
@end
SPEC_BEGIN(FooBarSpec)
describe(@"A newly manufactured car", ^{
it(@"should not be nil", ^{
[MyHelperClass externalHelperMethod:self forCar:[CarFactory makeNewCar]];
});
});
SPEC_END
Upvotes: 5
Reputation: 3980
You could also create a straight C function above the SPEC_BEGIN()
scope.
NSString *makeAString () {
return @"A String";
}
Or if you have helper functions that will be used across several Spec files, place these functions in a separate file and import the header. I've found this to be a great way to clean up my Specs.
Upvotes: 8
Reputation: 735
Create your helper function as a block just after the SPEC_BEGIN:
SPEC_BEGIN(MySpec)
NSDate* (^dateFromString) (NSString *) = ^NSDate* (NSString *dateString) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateFormat:@"MM-dd-yyyy"];
return [dateFormatter dateFromString:dateString];
};
describe(@"something", ^{
NSDate *checkDate = dateFromString(@"12-01-2005");
...
});
SPEC_END
Upvotes: 34