Helper functions in Kiwi specs
Asked Answered
A

3

14

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.

Athenaathenaeum answered 25/6, 2012 at 22:42 Comment(1)
see this github.com/kiwi-bdd/Kiwi/issues/138Everick
A
34

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
Abelabelard answered 3/8, 2012 at 18:9 Comment(1)
Is it possible to have an async helper? Let's say if I wanted to authenticate against a remote server in the helper.Trefoil
L
8

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.

Lorettelorgnette answered 21/12, 2012 at 20:59 Comment(3)
I could swear I tried that, but I don't know for sure anymore. I will have to go back and check it out. This is more or less what I wanted.Athenaathenaeum
This gives me the following warning: warning: no previous prototype for function '<function name>' [-Wmissing-prototypes] This can be solved by making the method static: static NSString *makeAString() { ... }Tantalic
@SebastienMartin I've never seen this error. Are you declaring the function before you're using it?Lorettelorgnette
I
5

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
Infold answered 27/11, 2014 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.