Groovy DSL fun again!


So I’m writing these ad-hoc Groovy scripts to update a chart on an internal wiki page when I start feeling the urge to play with the syntax. Groovy is so much fun to use that you just can’t help but mangle with things once you get the hang of it. Hi, I’m Cliff. You’re here because you like to alter the rules of your programming language while it’s running.

It’s been some years since I fooled with GSpec and all the meta-programming stuff. So now I start my latest script (half into the project) and decide to express what I want the script to work like before I write the code. It’s a fairly straight forward task and I find it very easy to bend Groovy syntax to say exactly what I’m thinking while remaining executable. So I start with this:

def whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString){
    return "I'm not converted yet! :("
}

def then(action) { action() }

def givenJson = '''
{"my-latest.apk":
    {"totalSizeFormatted":"14.84 MB","imagesSizeFormatted":"6.22 MB",
    "textSizeFormatted":"426.37 KB",
    "resourcesSizeFormatted":"2.04 MB","executableSizeFormatted":"1.15 MB","audioFilesSizeFormatted":"376.10 KB",
    "totalSize":15562499,"imagesSize":6517513,"textSize":436603,
    "resourcesSize":2141448,"executableSize":1202497,"audioFilesSize":385126},
}'''

def andGivenTableMarkup = '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 |
'''

def andGivenApkVersionString = '2.8.0.25'

def result = whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString)
then {
    assert result == '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 | 2.8.0.25 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 | 1174.31 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 | 2091.26 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 | 6364.76 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 | 426.37 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 46.09 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 | 15197.75 |
'''
}

Then taken some learning from my recent Python training I thought, “Hey, why not include this test as an expectations string at the bottom of my script, similar to how Python uses doc-strings!”

def expectations = """
def whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString){
    return "I'm not converted yet! :("
}

def then(action) { action() }

def givenJson = '''
{"my-latest.apk":
    {"totalSizeFormatted":"14.84 MB","imagesSizeFormatted":"6.22 MB",
    "textSizeFormatted":"426.37 KB",
    "resourcesSizeFormatted":"2.04 MB","executableSizeFormatted":"1.15 MB","audioFilesSizeFormatted":"376.10 KB",
    "totalSize":15562499,"imagesSize":6517513,"textSize":436603,
    "resourcesSize":2141448,"executableSize":1202497,"audioFilesSize":385126},
}'''

def andGivenTableMarkup = '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 |
'''

def andGivenApkVersionString = '2.8.0.25'

def result = whenWeConvertItToTableMarkup(givenJson, andGivenTableMarkup, andGivenApkVersionString)
then {
    assert result == '''\t| Version | 2.6.0.95 | 2.7.0.907 | 2.7.0.909 | 2.7.0.911 | 2.8.0.20 | 2.8.0.16 | 2.8.0.25 |
\t| Executable | 574.13 | 598 | 598.94 | 598.54 | 594 | 592.80 | 1174.31 |
\t| Resources | 1580 | 1720 | 1720 | 1720 | 1800 | 1800 | 2091.26 |
\t| Images | 3980 | 5240 | 5240 | 5240 | 6170 | 6160 | 6364.76 |
\t| Text | 264.35 | 278.59 | 278.57 | 278.59 | 293.30 | 293.93 | 426.37 |
\t| Audio Files | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 376.10 | 46.09 |
\t| Total | 11550 | 13110 | 13080 | 13110 | 14160 | 14370 | 15197.75 |
'''
}
"""

println expectations

Taking it a step further I can pass the expectation string to an eval call (or whatever the Groovy “eval” equivalent is, I’ve been mixing my scripting languages a lot these days…) and execute the test while passing the current object into the evaluated context. I can do all of this without frameworks or anything fancy. If I sprinkled just a little meta-programming into the mix then I could remove the definitions for the “then” and the “whenWeConvertItToTableMarkup” methods and have it read like a real spec!

How Many Emcees Must Get Dissed…?


So you’re a programmer?
Yes, yes, yes, yes, yes…
I code very deeply…
In about 4 seconds, a teacher will begin to speak
I code very deeply…

Hi, I’m Cliff. You’re here because you wish to know the answer to the age old question, a question that has been asked by many different people over the ages. (Yes some even asked this very question on Yahoo.) This question is generally understood to be it’s own answer. However, in today’s discussion we will revisit the question in code using test driven design as a unique experiment uncover the answer.

Before we begin, some elaboration is in order for those who do not have a background in heavy beats and sentences terminated by rhyming vocabulary. The question we must ask and answer is, “How many emcees must get dissed before somebody says don’t mess with Cliff?” (Astute readers will note that I am paraphrasing slightly from the original.) We ask this question because over the years there have been many emcees who have had their egos reduces to nothing merely because they didn’t understand the exact count or quantitative answer. “Is it 10, or 11? Was my number twelve? Oh, I lost my ticket!”, they would say on their way towards total annihilation. “What is an emcee?”, you ask. It is the phonetic spelling of one MC which (as Queen Latifah explains) is short for “Microphone Commando”. I digress…

So we begin with an iPhone Xcode 4.2 project which will generate an iOS 5.0 static library. Our end result will be a static library which will be able to be linked to any iPhone app that wishes to provide an answer to this very question. Please open you copy of Xcode and follow along. I named my Project “HowManyEmcees” and created it as a static lib project sacked in my “dev” folder. (Feel free to save your project where ever you see fit.) Make sure you have the “Include UnitTests” checkbox marked and also check the “Create a local git repository” option to enable source control. For some it will be difficult but it’s very important that you follow each step exactly. The idea is to recondition yourself from writing code before you know why you’re writing code. Our first test will be as follows.

//
//  HowManyEmceesTests.m
//  HowManyEmceesTests
//
//  Created by Clifton Craig on 12/27/11.
//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//

#import
#import "EmceeWarehouse.h"

@interface HowManyEmceesTests : SenTestCase

@end

@implementation HowManyEmceesTests

- (void)setUp
{
    [super setUp];

    // Set-up code here.
}

- (void)tearDown
{
    // Tear-down code here.

    [super tearDown];
}

- (void)testCanGenerateListOfEmcees
{
}

@end

We start by declaring the need for an “EmceeWarehouse” and beginning a test case that will eventually demonstrate how we get a list of Emcees from the EmceeWarehouse. That said, you can expect a warehouse full of emcees to get dissed in our example. Let’s continue with typical memory management etiquette assigning the warehouse in our setUp and clearing it in our teardown. (I could skip this step if I were to use the new iOS 5.0 ARC features but let’s keep things familiar and not introduce too much at once here.)

@interface HowManyEmceesTests : SenTestCase

@property (nonatomic, retain) EmceeWarehouse *emceeWarehouse;

@end

@implementation HowManyEmceesTests
@synthesize emceeWarehouse;

- (void)setUp
{
    [super setUp];

    self.emceeWarehouse = [[EmceeWarehouse alloc] init];
}

- (void)tearDown
{
    self.emceeWarehouse = nil;

    [super tearDown];
}

Now we hit Cmd+U, compile, crash, and understand that we need to actually have an EmceeWarehouse. It is very important that you compile at this point and verify all of the compile errors. If you are not getting compile errors then it is likely that you have not resisted the urge to correct the red flags in your editor as you went ahead and implemented the code before writing your test. If you don’t have errors, go back and delete your premature EmceeWareHouse, compile and crash. After crashing on compile create a plain old Obj-C object named EmceeWarehouse and add it only to the library (not the test) target. Compile, run (Cmd+U) and get your first green bar or passing test suite. (Why doesn’t Xcode unit testing feature green bars?) Back in our test method we express our intentions. This is the fun part because we can be as creative as we wish. I like to think of it as programming with the most dynamic language on the planet because you can change the way methods work as you write them without the penalty of recompiling or bug fixing. You’ll see what I mean in a moment.

- (void)testCanGenerateListOfEmcees
{
    id manyEmcees = [self.emceeWarehouse listOfEmcees];

    STAssertTrue([[manyEmcees class] isSubclassOfClass:[NSArray class]],
                 @"Expecting an instance of NSArray but got %@", [[manyEmcees class] description]);
}

Add the logic above to your test and compile, run and crash. If you didn’t crash you jumped ahead again. Delete your listOfEmcees implementation in “EmceeWarehouse.m” and start over. Note that the amount of code you delete and add later is directly proportional to the amount of unnecessary code found in projects that do not use TDD. As we iterate between test and code we are looking for the simplest thing that works which is the barest amount of code that can satisfy the most recent test, anything more will absolutely degrade the quality of your project. This will make more sense after a few iterations. Let’s look back at our test. It doesn’t quite fit what we are after. We are looking to get many different emcees from the warehouse, possibly all with varying skill levels. Lets change the test to make it more indicative of that.

- (void)testCanAskForManyDifferentEmcees
{
    id manyDifferentEmcees = [self.emceeWarehouse manyDifferentEmcees];

    STAssertTrue([[manyDifferentEmcees class] isSubclassOfClass:[NSArray class]],
                 @"Expecting an instance of NSArray but got %@", [[manyDifferentEmcees class] description]);
}

This contrived example illustrates an important point. Making changes to your tests should cost little if anything which highlights another valuable concept. Making changes to your product’s requirements should cost very little. In TDD, a test should be the direct result of a discussion of some product requirement and should closely follow or even echo a given requirement. Requirements change frequently because they cannot be completely understood until your product ages a little, so formalizing the requirements in test code is important. Also, if you are being penalized for changing your requirements then you will be less likely to make the necessary changes in your requirements thus suffocating your product. Now lets implement our warehouse just a little.

//  EmceeWarehouse.h
#import

@interface EmceeWarehouse : NSObject

-(id) manyDifferentEmcees;

@end

//  EmceeWarehouse.m
#import "EmceeWarehouse.h"

@implementation EmceeWarehouse

-(id)manyDifferentEmcees
{
    return nil;
}

@end

Cmd+U and crash! It’s like stumbling through a dark room with your hands extended reaching for the wall or nearby objects. We want to carefully approach our optimal solution without stepping passed it. The less code we use to solve a problem or requirement, the more power/flexibility we have to change existing requirements or add new ones. We need to make one minor change in “EmceeWarehouse.m” before we can move on.


-(id)manyDifferentEmcees
{
    return [NSArray array];
}

Now that we pass we can commit. Committing after every passing test is a good idea because it leaves a nice audit trail of how you grew your solution. One thing to note now is the return type of our method. Even though our test eventually compared the manyDifferentEmcees to an NSArray we didn’t formalize the return type in the method declaration. That optimization must be done after we go over the test a few times and get our initial pass because it allows us the time to mentally settle on the appropriate types. Once again, the barest amount of code to satisfy the requirement is what’s important. Then you go back and refine the requirements and finally the implementation. Looking back at our test we can ask ourselves, do we really want an NSArray or should it be an NSSet? Should we try to use an NSMutableArray? We’ll stay with NSArray since we probably want to go through emcees in a predictable order and also since each emcee will probably want to listen to the one before him. We’ll forgo the use of NSMutableArray externally because we don’t have a need to change the order or members of the array. That decision is difficult for some people because, as engineers, we like to expound on what we believe the optimal solution to be rather than allowing proper iteration to guide us. That is, we love to make those “experienced educated guesses” at what would most likely solve the problem. Making such assumptions (corruptions) is the actual equivalent of writing bugs into your software or pouring salt into the open wound. Let’s make the NSArray return type formal at this point run our tests to make sure they still pass and commit.

//  EmceeWarehouse.h
#import

@interface EmceeWarehouse : NSObject

-(id) manyDifferentEmcees;

@end

//  EmceeWarehouse.m
#import "EmceeWarehouse.h"

@implementation EmceeWarehouse

-(id)manyDifferentEmcees
{
    return [NSArray array];
}

@end

In our next requirement we explore how many emcees we’re prepared to devour. Recall above that we merely satisfied the requirement of being able to ask for emcees from the warehouse, now we need to count them and make sure we have enough to prove our street credibility. Pay attention to the fact that we are incrementally exploring what our requirements should be and using that to determine what code to write and how it should look. Add the next test.


-(void)testManyDifferentEmceesShouldIncludeMoreThanOne
{
    NSInteger howManyEmcees = [[self.emceeWarehouse manyDifferentEmcees] count];
    STAssertTrue(howManyEmcees > 1, @"Should have more than 1 emcee to prove street credibility. we count %i", howManyEmcees);
}

Compile, test, fail and fix the implementation to the simplest thing that works.


-(NSArray*)manyDifferentEmcees
{
    return [NSArray arrayWithObjects:@"This is not and Emcee",
            @"and neither is this",
            nil];
}

I like to push the needle towards stoopid sometimes as I add code that is obviously wrong. The point here is to force yourself to write the tests (or the “requirements” as I like to think of them) to expose the obviously wrong or missing code. We now have passing tests and an opportunity to commit. Commit the above changes and let’s move on to one of my favorite parts. Now it’s time to define what it means to be an actual “Emcee”. See the next code example.

-(void)testEachOfManyDifferentEmceesShouldBeAnActualEmcee
{
    for (id eachEmcee in [self.emceeWarehouse manyDifferentEmcees]) {
        //What do we do here???
    }
}

A heavy-handed approach would be to compare eachEmcee class against an actual class named “Emcee”. Since we haven’t thought that far in advance lets try something simple yet not so obvious.

    for (id eachEmcee in [self.emceeWarehouse manyDifferentEmcees]) {
        STAssertTrue([eachEmcee conformsToProtocol:@protocol(Emcee)],
                     @"How many emcees wanna be emcees? Never be emcees. Cause they can't emcee!");
    }

Protocols are mere abstractions that don’t need an implementation (similar to Java interfaces) and they are simple enough to allow us to specify our intention while allowing us to move on with developing the warehouse. I hit Cmd+U (you should too) after even the most minute source changes. It is a means of giving you instant feedback of what you did as well as how what you just did impacts the overall project. Our compiler (and our editor both) tells us we need to define the Emcee protocol. Now, towards the top of “EmceeWarehouse.h” add:

@protocol Emcee

@end

Cmd+U exposes the silly behavior in our warehouse. We need something that represents a real emcee so we’ll add the simplest thing that works. Put thins anywhere in your project (I included it at the bottom of “EmceeWarehouse.m”) to allow our test to pass:

@interface NSString(Emcee)
@end

@implementation NSString(Emcee)

@end

This is a category used only from within EmceeWarehouse.m so it does not need to have separate “.m” and “.h” files. I also like to patch up my implementation to reflect the new change:


-(NSArray*)manyDifferentEmcees
{
    return [NSArray arrayWithObjects:@"I wanna be an Emcee!",
            @"Now I'm an Emcee!",
            nil];
}

As you can see, right now it doesn’t take much to be an emcee. Make sure you commit your changes before moving on. Let’s make our warehouse just a little more interesting by including a capacity and making sure it’s always full to capacity.
HowManyEmceesTests.m

@interface HowManyEmceesTests : SenTestCase

@property (nonatomic, retain) EmceeWarehouse *emceeWarehouse;
@property (nonatomic, assign) NSInteger warehouseCapacity;

@end

@implementation HowManyEmceesTests
@synthesize emceeWarehouse;
@synthesize warehouseCapacity;

- (void)setUp
{
    [super setUp];
    self.warehouseCapacity = 100;
    self.emceeWarehouse = [[EmceeWarehouse alloc] initWithCapacity:self.warehouseCapacity];
}

Cmd+U crash with unrecognized selector “initWithCapacity:” sent to instance.
EmceeWarehouse.h

@interface EmceeWarehouse : NSObject

- (id)initWithCapacity:(NSInteger)aCapacity;
-(NSArray*) manyDifferentEmcees;

@end

EmceeWarehouse.m


- (id)initWithCapacity:(NSInteger)aCapacity /*we don't wanna do anything with the capacity yet!!!*/
{
    self = [super init];
    if (self) {
        //don't touch this part yet!!!
    }
    return self;
}

Cmd+U, pass, commit! Now we need to make sure we’re always full to capacity.
HowManyEmceesTests.m


-(void)testWarehouseIsFullToCapacity
{
    STAssertEquals((NSInteger)[[self.emceeWarehouse manyDifferentEmcees] count], self.warehouseCapacity,
                   @"EmceeWarehaouse should be full to warehouseCapacity");
}

Cmd+U fail, and fix:
EmceeWarehouse.h

@interface EmceeWarehouse : NSObject

- (id)initWithCapacity:(NSInteger)aCapacity;
-(NSArray*) manyDifferentEmcees;

@property(nonatomic, assign) NSInteger capacity;

@end

EmceeWarehouse.m

@implementation EmceeWarehouse
@synthesize capacity;

- (id)initWithCapacity:(NSInteger)aCapacity
{
    self = [super init];
    if (self) {
        self.capacity = aCapacity;
    }
    return self;
}

-(NSArray*)manyDifferentEmcees
{
    NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
    for (int countOfEmcees = 0; countOfEmcees < self.capacity; countOfEmcees++) {
        [soManyDifferentEmcees addObject:@"I wanna be an emcee!!"];
    }
    return soManyDifferentEmcees;
}

@end

Now when you have so many different emcees there’s bound to be a sucka in the mix! To be specific, a sucka emcee is the one that will cop out in the midst of a challenge. He’s the one that has no heart and is afraid to battle- the one emcee that’ll say “Don’t mess with Cliff”, thus terminating what eventually become an infinite loop, or never ending round of battles. Many people don’t understand what exactly does it mean to be an emcee. Our next round of tests will explain it very clearly. At the very bottom of “HowmanyEmceesTests.m” we’ll add:

#pragma mark - EmceeTests

@interface EmceeTests : SenTestCase

@property (nonatomic, retain) id theEmcee;
@end

@implementation EmceeTests
@synthesize theEmcee;

-(void)setUp
{
    [super setUp];
}

-(void)tearDown
{
    self.theEmcee = nil;
    [super tearDown];
}

@end

It’s more common to use different test case files but for our purposes we can stuff everything in one file. Hit Cmd+U and verify both test case classes show as being executed. (You can commit here as well.) Add our first definition of a real emcee:
HowManyEmceesTests.m

-(void)testAnEmceeCanBeASucka
{
    self.theEmcee.isSucka;
}

Cmd+U (after every little change, remember?) forces us to go add a property that will expose the true heart of each emcee, showing if he’s hardcore or not. (Yeah, yeah, I know! Our emcee could be a “she” as well! and she could also be hardcore.) Let’s define that property.
EmceeWarehouse.h

@protocol Emcee

@property (nonatomic, readonly) BOOL isSucka;

@end

Adding the following to the NSString category in “EmceeWarehouse.m” will eventually give us a warehouse full of sucka emcees:
EmceeWarehouse.h

@implementation NSString(Emcee)
@dynamic isSucka;

-(BOOL)isSucka
{
    return YES;
}

Cmd+U, pass and commit. We’re at a point where we should break out two different classes of emcees. Enter ChampionEmcee and SuckaEmcee, both of these will probably extend the base class of Emcee, right? Before we get ahead of ourselves let’s start from the tests since we have some cleanup to do. First create an empty file named EmceeWarehouse.m and cut/paste the following from “HowManyEmceesTests.m” (copy the imports of course but cut everything else):
HowManyEmceesTests.m

#import
#import "EmceeWarehouse.h"

#pragma mark - EmceeTests

@interface EmceeTests : SenTestCase

@property (nonatomic, retain) id theEmcee;
@end

@implementation EmceeTests
@synthesize theEmcee;

-(void)setUp
{
    [super setUp];
}

-(void)tearDown
{
    self.theEmcee = nil;
    [super tearDown];
}

-(void)testAnEmceeCanBeASucka
{
    self.theEmcee.isSucka;
}

@end

Commit after verifying that this new test case is associated with the tests target and its tests are still being executed. (In my case I believe it defatted to the test target since that was the active target.) Change #import "EmceeWarehouse.h" to #import "Emcee.h". Compile (Cmd+U), crash, and know that you now need to create and Emcee Objective-C file. Pay attention to how we always use the Cmd+U sequence to let either the compiler or the runtime let us know when we need to add more code. It is a difficult habit to build, breaking out of the “I know I need to do X” mentality. The more frequently you use Cmd+U the more you get used to seeing what doesn’t work while familiarizing with all the different errors that would otherwise confuse you. Add the new “Emcee” class and Cmd+U again to learn that you now need to move the protocol definition out of “EmceeWharehouse.h”.
EmceeWharehouse.h

#import "Emcee.h"
@protocol Emcee

@property (nonatomic, readonly) BOOL isSucka;

@end

Change the setUp to make sure we are exercising the Emcee class:

-(void)setUp
{
    self.theEmcee = [[[Emcee alloc] init] autorelease];
    [super setUp];
}

Cmd+U will show failure since we never declared/synthesized the isSucka property. Make the Emcee class follow the Emcee protocol and synthesize the isSucka property.

@interface Emcee : NSObject <Emcee>

@end

@implementation Emcee
@synthesize isSucka;

@end

Test (Cmd+U), pass and commit. Change the EmceeWarehouse manyDifferentEmcees method to use our new class and remove the ad-hoc category on NSString.

-(id<Emcee>)anyOldEmcee
{
    return [[[Emcee alloc] init] autorelease];
}

-(NSArray*)manyDifferentEmcees
{
    NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
    for (int countOfEmcees = 0; countOfEmcees < self.capacity; countOfEmcees++) {
        [soManyDifferentEmcees addObject:[self anyOldEmcee]];
    }
    return soManyDifferentEmcees;
}

Cmd+U, pass, commit. Now add the following to the bottom of the EmceeTests file:

@interface SuckaEmceeTests : EmceeTests

@end

@implementation SuckaEmceeTests

-(void)setUp
{
    [super setUp];
    self.theEmcee = [[[SuckaEmcee alloc] init] autorelease];
}

-(void)testASuckaEmceeWillAlwaysBeASucka
{
    STAssertTrue(self.theEmcee.isSucka, @"A sucka emcee will always be a sucka!");
}

@end

Hitting Cmd+U makes our toolchain inform us that we need to define a SuckaEmcee:
Emcee.h

@interface SuckaEmcee : Emcee

@end

Emcee.m

@implementation SuckaEmcee

@end

Hitting Cmd+U once more reminds us that a sucka emcee will always be a sucka. We must code our new class this way.
Emcee.m

@implementation SuckaEmcee

-(BOOL)isSucka
{
    return YES;
}

@end

Cmd+U, pass, and commit. Back in our EmceeTests class. We need to make our Emcees spit a lil’ sumn sumn.

-(void)testAnEmceeCanSpitSomething
{
    NSString *aLilSumnSumn = [self.theEmcee spitSomething];
    STAssertNotNil(aLilSumnSumn, @"aLilSumnSumn should never be nil because that's just not John Blaze. Y'know?");
}

Cmd+U makes us add the following:

@protocol Emcee <NSObject>

@property (nonatomic, readonly) BOOL isSucka;

-(NSString *)spitSomething;

@end

//And in our base class
@implementation Emcee
@synthesize isSucka;

-(NSString *)spitSomething
{
    return nil;
}

@end

Cmd+U shows two errors for the one test. This is important to pay attention to since we’ve added the expectation to the base test case for emcee it will apply to all Emcees, even the suckas. Add the simplest thing that works:

-(NSString *)spitSomething
{
    return @"I'll battle any sex or any race. You beating me is like Billy Crystal playing Scarface.";
}

That’s not necessarily the simplest thing but it’s colorful enough to get the point across. Now let’s see what happens when one Emcee spits something at another.

-(void)testAnEmceeCanSpitSomethingAtAnother
{
    id<Emcee> anotherEmcee = [[[Emcee alloc] init] autorelease];
    NSString *aLilSumnSumn = [self.theEmcee spitSomething:anotherEmcee];
    STAssertNotNil(aLilSumnSumn, @"aLilSumnSumn should never be nil because that's just not John Blaze. Y'know?");
}

Editor and compiler errors tell us we need to do something, something simple.

-(NSString *)spitSomething:(id<Emcee>)anotherEmcee
{
    return nil;
}

Cmd+U runs and shows us where we’re not so John Blaze. A simple fix would be to make the new spitSomething: work like the other.

-(NSString *)spitSomething:(id<Emcee>)anotherEmcee
{
    return [self spitSomething];
}

Now we’re going to see an Emcee just getting dissed.

-(void) testAnEmceeJustGotDissed
{
    [[[[Emcee alloc] init] autorelease] spitSomething:self.theEmcee];
    self.theEmcee.justGotDissed;
}

Cmd+U compile error tells us to add the missing method.
Emcee.h

@protocol Emcee <NSObject>

@property (nonatomic, readonly) BOOL isSucka;
@property (nonatomic, assign) BOOL justGotDissed;

Emcee.m

@implementation Emcee
@synthesize isSucka;
@synthesize justGotDissed;

Now add our expectation to our test case.

-(void) testAnEmceeJustGotDissed
{
    [[[[Emcee alloc] init] autorelease] spitSomething:self.theEmcee];
    STAssertTrue(self.theEmcee.justGotDissed, @"The Emcee just got dissed. Property check should confirm this.");
}

The simplest solution:

-(BOOL)justGotDissed
{
    return YES;
}

Of course it shouldn’t make sense. We want to write another test that explains why tour current solution is less than optimal:

-(void)testAnEmceeDidNotJustGetDissed
{
    STAssertFalse(self.theEmcee.justGotDissed, @"Nobody spit anything at the emcee. He did not just get dissed");
}

All along we are adding documentation along side our new software components. This is the best kind of documentation because it is executable and always up to date. When something breaks we have documentation explaining how we expect things to work and where the breakage is. Removing the formal definition from our implementation will cause it to fall back on the synthesized definition which will always return NO when we asked if we just got dissed. That will fix our latest test but break our earlier test. We are forced to change the state of the other emcee as we spit something at another emcee.

-(NSString *)spitSomething:(id<Emcee>)anotherEmcee
{
    anotherEmcee.justGotDissed = YES;
    return [self spitSomething];
}

//Remove/delete this...
//-(BOOL)justGotDissed
//{
//    return NO;
//}

Cmd+U to validate our above changes then feel free to delete the commented code. Cmd+U can be used to confirm our refactoring did not alter behavior prior to commiting. Congratulations! We have demonstrated how an emcee just got dissed. We’re almost there! A couple more changes are in order. First we need to elaborate on the SuckaEmcee. You see, a SuckaEmcee should say “Don’t mess with Cliff!” after he just got dissed because he’s soft. We need to add a test to document and demonstrate the idea. At the bottom of EmceeTests.m inside our SuckEmceeTests add the following:
EmceeTests.m

-(void) testASuckaEmceeJustGotDissed
{
    [[[[Emcee alloc] init] autorelease] spitSomething:self.theEmcee];
    STAssertEqualObjects([self.theEmcee spitSomething], @"Don't mess with Cliff!",
                   @"We expect the SuckaEmcee to be soft and tell others 'Don't mess with Cliff'.");
}

Notice how we really don’t need comments to explain what’s happening. Our expectations are inlined as code and our logic echoes our use cases. We can use the simplest thing that works here. At the bottom of Emcee.m in the @implementation for SuckaEmcee, we add this:

-(NSString *)spitSomething
{
    return @"Don't mess with Cliff!";
}

The SuckaEmcee feels slightly incomplete. We want our sucka to try to spit lil’ something on occasion, because he is an Emcee after all. The best way to demonstrate this is in our definition of an Emcee in the EmceeTests. We add a new test.

-(void) testAnEmceeWhoHasNotJustGotDissedWillNotShowFear
{
    STAssertFalse(self.theEmcee.justGotDissed, @"Given an Emcee that has not yet been dissed...(sanity check.)");
    STAssertFalse([[self.theEmcee spitSomething] isEqualToString:@"Don't mess with Cliff!"],
                  @"Any emcee will try to spit something before being dissed.");
}

Our test is showing us how our SuckaEmcee is not really behaving as an Emcee should. In plain slanglish, our current emcee is always punking out. We have to fix this since our sucka has “Emcee” in it’s class name and in it’s class hierarchy. In our SuckaEmcee @implementation we make it try to spit something before getting dissed:

-(NSString *)spitSomething
{
    if (self.justGotDissed) {
        return @"Don't mess with Cliff!";
    } else {
        return [super spitSomething];
    }
}

Cmd+U pass, and commit. Now there’s still an issue with the each Emcee in our EmceeWarehouse. Among every group of Emcees you’re bound to find a sucka. Lets add one more test to our HowManyEmceesTests to make sure.

-(void)testThereShouldBeASuckaEmceeInTheWarehouse
{
    NSUInteger locationOfSucka = [[self.emceeWarehouse manyDifferentEmcees] indexOfObjectPassingTest:^BOOL(id eachEmcee, NSUInteger eachIndex, BOOL *stop){
        return eachEmcee.isSucka;
    }];
    STAssertFalse(locationOfSucka == NSNotFound,@"Location of our SuckaEmcee should NOT be NotFound.");
}

Cmd+U and we see a new but expected failure from the assert we just coded. We need to change the implementation of our manyDifferentEmcees method using the most simplest approach:

-(NSArray*)manyDifferentEmcees
{
    NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
    for (int countOfEmcees = 0; countOfEmcees &lt; self.capacity; countOfEmcees++) {
        [soManyDifferentEmcees addObject:[self anyOldEmcee]];
    }
    [soManyDifferentEmcees addObject:[[[SuckaEmcee alloc] init] autorelease]]; //tack on a SuckaEmcee
    return soManyDifferentEmcees;
}

Cmd+U and guess what? We fixed our test and broke another. Our TestCases just deposited a few dollars into our development account! Our test, testWarehouseIsFullToCapacity, complains that our warehouse must be flu to capacity. We cannot just add a sucka on the end because he won't fit. For now we just tweak the manyDifferentEmcees method once again to make room.

-(NSArray*)manyDifferentEmcees
{
    NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
    for (int countOfEmcees = 0; countOfEmcees &lt; self.capacity - 1/* Leave room for desert, the last Emcee is gonna get ate!*/; countOfEmcees++) {
        [soManyDifferentEmcees addObject:[self anyOldEmcee]];
    }
    [soManyDifferentEmcees addObject:[[[SuckaEmcee alloc] init] autorelease]]; //tack on a SuckaEmcee
    return soManyDifferentEmcees;
}

At this point we've built enough infrastructure to answer our original question but this solution is a little boring and completely predictable since we always fill our warehouse with a sucka on the end. We have tests to cover our next move, refactor! We want to take a different approach to making sure there's a sucka emcee in the crowd. First restore our manyDifferentEmcees method to it's original form. Revert the EmceeWarehouse.m file so it looks like this:

-(NSArray*)manyDifferentEmcees
{
NSMutableArray *soManyDifferentEmcees = [NSMutableArray array];
for (int countOfEmcees = 0; countOfEmcees &lt; self.capacity; countOfEmcees++) {
[soManyDifferentEmcees addObject:[self anyOldEmcee]];
}
return soManyDifferentEmcees;
}

Cmd+U and fail on the original assert failure. Next we change the anyOldEmcee method to return either an Emcee or a sucka based on a random value:

-(id)anyOldEmcee
{
if ((arc4random() % 100) &gt; 95) {
return [[[SuckaEmcee alloc] init] autorelease];
} else {
return [[[Emcee alloc] init] autorelease];
}
}

That should give us a rough distribution of 5% sucka Emcees in our warehouse. We can adjust the percentage to our liking as our needs mature. For now this will do. Our last bit of code is intended to test each emcee. Create the following test case:

-(void)testHowManyEmceesMustGetDissed
{
    id cliff = [[[Emcee alloc] init] autorelease];
    NSUInteger locationOfEmceeThatJustGotDissed = [[self.emceeWarehouse manyDifferentEmcees] indexOfObjectPassingTest:^BOOL(id eachEmcee, NSUInteger eachIndex, BOOL *stop){
        [cliff spitSomething:eachEmcee];
        *stop = [[eachEmcee spitSomething] isEqualToString:@"Don't mess with Cliff!"];
        return *stop;
    }];
    STAssertEquals(locationOfEmceeThatJustGotDissed, (NSUInteger)0,@"%i emcees just got dissed", locationOfEmceeThatJustGotDissed + 1);
}

You may want to run this test more than once. It illustrates an important technique I often use when doing TDD. It’s what I call the discovery test. Whenever I have an API call that produces an unknown (or in this case variable) value that I want to discover, I write a failing test which outputs the value of the API call as part of the assert description. In the above example we finally discover how many emcees just got dissed, before somebody says, “don’t mess with Cliff!” I leave you to mull over it for a while. Leave comments if you will. G’night.

TDD- Is it worth it?


It’s been a long time, I shouldn’t have left you… without some strong code to step to. Step to, step too… step to… (Cliff re-quoting Timbaland re-quoting
Rakim…)

I’ve been attending a Srcum certification course led by none other than James Coplien. This guy is fantastic and I’ve already learned a great deal about the practice in the one day I’ve spent with him. Now here’s the controversial topic. Jim, is totally against TDD. If you know me, I am from the polar opposite camp. I had a breif dsicussion with Jim yesterday which I plan to continue today if he allows the time. In the interim I took the liberty of reviewing some of a standard email he sends to people like me who are unaware/unsure of his strong opposing position. The 1st link features Jim in a debate with a person I admire, Uncle Bob Martin from Object Mentor. This debate felt almost identical to my discussion with Jim yesterday and while both leave me unconvinced that TDD is harmful I remain open-minded. I am so open-minded to Jim’s position that I wanted to rush a quick post this morning to explain where I could potentially agree that TDD does more harm than good.

Testing at the wrong level

One of Jim’s primary arguments is that developers practice TDD at the wrong level, the class level that is not responsible for external features and contracts. This leads to code bloat from the test and gives you the wrong architecture from the onset. I whole heartedly agree with Jim on this point and it is something I still find myself doing from time to time. The practice requires a certain discipline and experience that you get only from making this and other similar missteps. In all, your design should come from your specifications or contracts and these should precede your implementation. I believe (without asking him) that Jim would agree with me here.

Poorly factored unit tests

One of the primary reasons TDD fails is because many miss the last R in the RGR cycle. RGR stands for Red Green Refactor. That means you write a failing test (reports red), make it pass (reports green), then you refactor both you system under test and your test code. I’ve made the mistake of not properly refactoring my test code in a hurry to move onto the next thing. Your test code should read like a contract or a usage guide for how to interact with your code. In practice the test code tends to grow rather quickly, which exceeds a developer’s ability to properly maintain it, which leads to the code bloat mentioned above. This step takes discipline and can be easy to neglect even for experienced developers.

Writing too much test or too much code

Following Uncle Bob, the TDD cycle is a tight and minimalistic cycle where you write only enough test to state or explore the current part of the specification you’re working on and only enough code to satisfy that test. Problems arise from writing too much test code without iterating over implementation code which is the inverse of YAGNI, YAGII! (You Ain’t Gonna Implement It.) Also you get into trouble from writing too much implementation code without a requirement or specification to justify it.  The power comes from the iterative approach to explorative development. As you iterate you uncover pieces of the spec that are not complete which might require discussion with your QA or business analyst and trigger discussions and that leads to an important distinction I’d like to mention. Many people make a distinction between bugs and features. I see them as one in the same. A bug is simply a non-feature or a hole in your spec. It represents some edge case or usage scenario that has not been explored which leads to errant unexpected or undefined behavior. You iterate on these the same as you do your features by amending your spec and filling in the holes in both the spec and your test cases which should mirror your spec.

I have to cut this short now since class is starting. It’s an interesting topic and I’d love to hear more about what Jim and others have to say on the topic.

If you try to fail, and succeed, which have you done?


From T.D.D. training two weeks ago I learned that failing is just as important as passing. More specifically certain tests are expected to fail and you need to verify that they do. It’s a little counter intuitive but think about it. The first kind of failing test that deserves our attention is the initial test. The first time you write a test it should fail and you should verify that it does. That ensures that you are actually adding the intended behavior when you finally do get a green bar.

Another type of important failure is the resilience test. These are test that check your code’s resilience to bad input. Lets just pretend that you have this:

class TeleporterTest extends TestCase {
   public void testTeleport() throws Exception {
      Teleporter hiro = createTeleporter();
      hiro.telelportTo(new Planet(Planet.MARS));
   }
}

Here we are exercising Hiro’s ability to teleport to other planets which we would expect to fail. (It should fail because there’s no oxygen on Mars which would in effect kill our Hiro or Hero, if you will.) We want our Hiro to throw an Exception on inter-planetary travel… something like InterplanetaryException. This is a situation where we try to fail. If you run the test as is and it green-bars what have we done? Have we succeeded or have we failed? It’s a really mind-twisting bit of code the first time you write such a test because you have to think opposite then opposite of that opposite then rationalize the intent of double negatives and all.

So how do we assert an Exception in JUnit? (It turns out that the folks at CxxUnit have done a much better job at the task.) First you have to execute the code that you’d expect to throw the Exception as above then you have check that the exception is thrown. The easy way to do that is to put another line of code after the line you’re testing, an “if-we-get-here” line. Because if we get that far then the Exception hasn’t happened which means we’ve failed.

class TeleporterTest extends TestCase {
   public void testTeleport() throws Exception {
      Teleporter hiro = createTeleporter();
      hiro.telelportTo(new Planet(Planet.MARS));
      fail("Hiro shouldn't teleport across planets!");
   }
}

We run the above and get our red bar which tells us to change/add the logic necessary to trap for bad input. Assuming the createTeleporter() method just returns “new HiroNakamura()” we’d do something like this.

class HiroNakamura {
   public void teleportTo(Object location) {
      if(location instanceOf Planet) 
      { throw new InterplanetaryException(); //extends RuntimeException }
      //...
   }
}

But wait! That causes our test to error because an exception is thrown. You have to catch the exception in your test so that the test framework doesn’t catch it and abend. We do something like this:

class TeleporterTest extends TestCase {
   public void testTeleport() throws Exception {
      Teleporter hiro = createTeleporter();
      try {
         hiro.telelportTo(new Planet(Planet.MARS));
         fail("Hiro shouldn't teleport across planets!");
      } catch(Exception e) {
         //we expect an exception which means we're good
      }
   }
}

Now we’re in big trouble. It is so typical to make the above mistake then live with the consequences days or months later. (If you know where the problem is keep quiet so the people in the back can concentrate.) What happens if later on somebody removes the guard clause in HiroNakamura? Or what happens when we create a new Teleporter implementation (PeterPatrelli) and attempt to reuse the above test logic? Let’s consider the first case where somebody thinks that the Planet object would be necessary for qualifying a location. In other words we want to be able to teleport to “Planet earth = new Planet(Planet.EARTH)” after we’ve set a country on it like, “earth.setCountry(“Japan”);”. So we remove the check at the beginning of Hiro’s teleportTo method and the test passes! That’s no good because now we can also send Hiro to Pluto and freeze him to death. The problem comes from the fact that we set out to fail and succeeded in failing which gave us a false sense of success. (That makes sense, right?) Instead should we have set out to succeed in failing and properly asserted our failure for success? Let’s look at our test.

class TeleporterTest extends TestCase {
   public void testTeleport() throws Exception {
      Teleporter hiro = createTeleporter();
      try {
         hiro.telelportTo(new Planet(Planet.MARS));
         fail("Hiro shouldn't teleport across planets!");
      } catch(Exception e) {
         //we expect an exception which means we're good
      }
   }
}

Why is it no longer failing when the Exception doesn’t happen? What’s really going on? Well we teleport and then we run the “we-shouldn’t-get-this-far” line and that should fail the test right? Well it would fail the test because it throws an AssertionFailedError which we blindly catch as Exception and silence with our naive comment that states stoopidly that we expect an Exception. (Never ever EVER catch or expect Exception!) Instead we should have caught the right type of exception which would not only self document the intent of the desired behavior but would have kept us safe from future modifications.

class TeleporterTest extends TestCase {
   public void testTeleport() throws Exception {
      Teleporter hiro = createTeleporter();
      try {
         hiro.telelportTo(new Planet(Planet.MARS));
         fail("Hiro shouldn't teleport across planets!");
      } catch(InterplanetaryException e) {
         //we expect an InterplanetaryException which means we're good
      }
   }
}

So now I ask the above question. If you try to fail, and succeed, which have you done?