Cuckoo for Cocoa Dev

A blog for all those Cuckoo for Cocoa Development

Behavioral Driven Development (BDD) Using CEDAR Part 1 - Easy Stuff

While many of us remember the “cowboy” coding days of the wild wild development west (some of us are still living there), in this day and age of modern development, we need to provide proof that our code does what it is supposed to. We can prove the viability of our code using different testing approaches (integration testing, functional testing, etc.), but for most developers the first line of testing defense is creating unit tests.

For this post, I will discussing test driven development using a BDD style testing framework called CEDAR (You can find it here). Lets begin by thinking of what we want to develop, as we will write descriptive tests for our class that will be tested. For this exercise, I want to create a simple (very simple) Super burrito object that has all the ingredients that you would find in a tortilla rolled up. First lets create a test that tests a super burrito:

SuperBurritoSpec.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#import "SuperBurrito.h"

using namespace Cedar::Matchers;
using namespace Cedar::Doubles;

SPEC_BEGIN(SuperBurritoSpec)

describe(@"SuperBurrito", ^{
    __block SuperBurrito *superBurrito;

    beforeEach(^{
        superBurrito = [[SuperBurrito alloc] init];
    });

    it(@"creates a super burrito", ^{
        superBurrito should_not be_nil;
    });
});

SPEC_END

Since test class won’t even compile, let’s go ahead and create our empty SuperBurrito class.

SuperBurrito.h
1
2
3
@interface SuperBurrito : NSObject

@end
SuperBurrito.m
1
2
3
4
5
#import "SuperBurrito.h"

@implementation SuperBurrito

@end

Now that we actually have a SuperBurrito class, we can run the test with success!

1
2
3
4
5
6
7
Running With Random Seed: 8722

.

Finished in 0.0003 seconds

1 examples, 0 failures

Since nobody likes an invisible burrito, now we need ingredients. Before we add these ingredients to the SuperBurrito class itself, lets create a failing test:

SuperBurritoSpec.mm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import "SuperBurrito.h"

using namespace Cedar::Matchers;
using namespace Cedar::Doubles;

SPEC_BEGIN(SuperBurritoSpec)

describe(@"SuperBurrito", ^{
    __block SuperBurrito *superBurrito;

    beforeEach(^{
        superBurrito = [[SuperBurrito alloc] init];
    });

    it(@"creates a super burrito", ^{
        superBurrito should_not be_nil;
    });

    it(@"has correct super burrito ingredients", ^{
        superBurrito.ingredients should equal(@[@"Tortilla", @"Carne Asada", @"Refried Beans", @"Spanish Rice", @"Salsa", @"Sour Cream", @"Guacamole", @"Cheese"]);
    });
});

SPEC_END

Again, since we don’t have an ingredients property and won’t even compile, let’s add it:

SuperBurrito.h
1
2
3
4
5
@interface SuperBurrito : NSObject

@property (strong, nonatomic) NSArray *ingredients;

@end

Now we can run the test and get our first failure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Running With Random Seed: 6224

.F

FAILURE SuperBurrito has correct super burrito ingredients
/CuckooWCEDAR/Specs/SuperBurritoSpec.mm:20 Expected <(null)> to equal <(
    "Tortilla",
    "Refried Beans",
    "Spanish Rice",
    Salsa,
    "Sour Cream",
    Guacamole,
    Cheese
)>


Finished in 0.0084 seconds

2 examples, 1 failures

Even though we now have an ingredients property that is an NSArray, we still aren’t populating it with the ingredients that we expect. Let’s go ahead and set that up in the init method:

SuperBurrito.m
1
2
3
4
5
6
7
8
9
10
11
12
@implementation SuperBurrito

- (id)init
{
    self = [super init];
    if (self) {
        self.ingredients = @[@"Refried Beans", @"Spanish Rice", @"Salsa", @"Sour Cream", @"Guacamole", @"Cheese"];
    }
    return self;
}

@end

When we re-run the test, we now have two passing tests.

1
2
3
4
5
6
7
Running With Random Seed: 8971

..

Finished in 0.0003 seconds

2 examples, 0 failures

As you can see can use CEDAR to create descriptive failing tests to drive our real SuperBurrito implementation. While this SuperBurrito class isn’t particularly helpful, it is a quick way to see how we can get started. The SuperBurrito can be found on Github.

In my next post I will cover test-driving a class that is more useful. While Super Burritos are awesome in real life, in the digital world, they aren’t all that helpful. Then again, maybe CLU, TRON and Kevin Flynn would have had a better time in the grid if they did have some to munch on.

Comments