![]() |
Articles Feed |
Categories
Archives
- July 2010 (5)
- June 2010 (4)
- April 2010 (3)
- March 2010 (2)
- February 2010 (2)
- January 2010 (1)
- December 2009 (1)
- October 2009 (2)
- September 2009 (2)
- August 2009 (1)
- July 2009 (5)
- June 2009 (2)
- May 2009 (2)
- April 2009 (8)
- March 2009 (7)
- January 2009 (2)
- December 2008 (3)
- November 2008 (5)
- October 2008 (4)
- September 2008 (6)
- August 2008 (4)
- July 2008 (5)
- June 2008 (5)
- May 2008 (4)
- April 2008 (2)
- February 2008 (4)
- January 2008 (2)
- December 2007 (2)
- November 2007 (2)
- October 2007 (2)
- September 2007 (1)
- August 2007 (3)
- July 2007 (1)
- June 2007 (4)
- May 2007 (7)
- April 2007 (2)
- February 2007 (3)
- January 2007 (3)
- November 2006 (3)
- October 2006 (3)
- September 2006 (17)
- November 2004 (1)
International Craftsman Swap Day 3
by: eric | June 23rd, 2010 | 0 comments »
Got Ruby?
After attending tonights got:ruby I became obsessed with and started installing rvm. It worked swimmingly, and I’m looking forward to getting my development machine off of the embarrassingly low version of Ruby and experimenting on the latest versions without (unintentionally) screwing up my production environment. Indeed after this week I’ve got a lot to google, lookup, and research. I’ve decided I have got to get good at JQuery - probably using it on a small Rails 3 project in the near future - and learned that Jasmine has it all over ScrewUnit. This may mess up my Haskell plans - not that I’ve ever messed that up before. After that we played a lot of ping-pong, then I decided to clean up my hard drive, because it was really time. Then I realized if I’m gonna do this project as Rails3, I better make sure I can deploy it on dreamhost with bundler.
If this sounds like procrastinating it’s cause it is. I also checked email, read Anders’ blog on the elabs.se site, and watched some of Germany beating Ghana. None of this is writing the blog post and that’s because today’s blog post is going to be hard. Let’s get this out of the way first. Today was another great day at ELabs. With my Jet Lag finally kicked I really was able to contribute, using a couple ideas we’ve had before on 8th Light projects to get some cool work done on the project I’ve been working on this week. I even wrestled for the keyboard a bit (although they have two keyboards - so it was lonely, I wrestled with Pixie) then we topped it all off a cool Ruby user group meeting. The meeting was last minute, so they had lightning talks where CJ talked about Bundler and rvm, Jonas talked about a Javascript testing plugin he’s working on, we puzzled over a problem one of the other developers was having and even looked at Omni Graffle. Now that I’m awake the ELabs guys had to suffer my jokes like the 8th Light guys do all the time. Now they know why they sent me out of the country.
What’s been really nagging at me has to do with the way that the ELabs boys work. See they are what Brian Marick would call “classicist” TDDers - they essentially never use mocks. I on the other hand generally mock out a lot. What Jonas said to me was, and I’m going from memory here, “I’d rather the tests run slow than be right.” Of course taken as stated, this is a truism. Nobody is voting for slow tests, although I might argue that the tests that verify correctness are often different than unit tests, and that unit tests are verifying a different thing. Aside from speed mocks provide value in designing apis by letting you design it with a client using it, before the object itself exists, and in thinking of systems as objects passing around messages you can really focus on their interactions instead of the implementation details. Mocks lead to a cleaner design all told….except….
Except I usually stub out things for speed. Objects I’m stubbing are webservices, database objects, file access, etc. And in the best cases the benefit I get is speed, and in the worst cases I get a tangled mess of mocks where my code and tests are coupled, but nothing necessarily works. I’ve completely traded speed for correctness. Why is that? Why am I not getting all the purported benefits of mocking.
In a related note on the way here I started reading “growing object oriented software, guided by tests” by Steve Freeman and Nat Pryce. In a throw away comment they say, “Never mock out third party API’s, write thin classes that wrap those with integration tests, and mock out your objects interaction with those classes.” Now maybe you think you haven’t done this, but let me give you some typical examples of mocks:
- IO.stub!(:read).and_return(mock_file)
- ActiveRecord.should_receive(:find).with(1)
Well look at that - those are two third party API’s aren’t they? And they are often mocked out everywhere! Trading speed for correctness again. “Okay fancy boy”, you’re saying - and really why are you calling me that, “Then we shouldn’t use mocks. Problem solved.” Not so fast. Have you ever had the problem where you are testing that an object gets saved and you do this:
object.should_receive(:update_attributes).with({:my => value})
but then you think, “Gosh I really don’t care how they save the values, I just care that it gets saved.” Right now you have to call update_attributes to make this pass, but you could call update_attribute, or set the object and save!, or hell use SQL although you shouldn’t. This makes for a crappy test - one you’re likely to break then fix later instead of changing in the deliberate process of TDD. What if instead you did this:
object.should_receive(:update_my_value_to).with(value)
Of course the other things are still true - assuming it’s an active record object, but maybe it’s not. Maybe it’s a wrapper around it, or maybe it’s datamapper object, I don’t really don’t care. I’ve gone ahead and mocked this call because that’s the call I really want to see - and somewhere else I’ve test driven that call against the database. Now let’s imagine you’ve got more complicated scenarios. Ever done this?
object.should_receive(:get_this).and_return(object2)
object2.should_receive(:is_true?).and_return(false)
This is a simple example - but I’m sure you’ve seen worse. The problem is again that you really need one method, maybe two, but you probably figured out in your head the algorithm beforehand, then test drove it. Maybe you know if object2 was true you needed to set unrelated object3’s flag - so you started writing those tests. Let’s look at that rule again though - don’t mock a third party API. Well what defines a third party API? Is it a third party if another company wrote it? How about the same company - but on a different project? Or the same project but a long time ago? Or YOU six weeks ago and you forgot it. Isn’t it a third party API again? What’s the difference? Should you then mock out objectnew - and test drive it with real objects? Because it’s pretty clear the API you want doesn’t exist yet, and that’s the crux of my long wrambling argument that I’ll probably better express and codify when it’s not late and I’m not tired:
Stop mocking the API you already have - mock the API you need
And then if by chance it matches the API you already have - by all means just substitute the real object in. But write the implementation with mocks first - without using any real API unless it matches coincidentally. Pretend the object doesn’t exist yet, and then mock. And maybe then you’ll get what you’re looking for.
Eh - or maybe I should go write some Javascript.
International Craftsman Swap Day 2
by: eric | June 22nd, 2010 | 2 comments »
CJ on his way to work
Before I get into some of the details of day #2 at eLabs, let me dispell a few myths about Sweden that my American readers may still believe.
Swedes buy all their furniture at IKEA
This is of course a silly idea, caused by the prominence of the IKEA brand in the United States. In fact IKEA accounts for a mere 83% of the furniture market here in Sweden, with the rest of the furniture being bought at independent specialty stores such as Wal-Mart.
Ski jumping is the primary form of transportation
Swedes have a wide variety of commuting options available to them. By far the most popular is to bike to work at speeds of upwards of 300 miles an hour, using the bodies of pedestrians to slow your bike down when you arrive at your office. The speed is necessary to outrun the second most popular form of transportation, the electric trams. The trams take a convenient route to your office, assuming they don’t fly off the tracks. Which they do, often. Ski jumping is naturally third, keeping the commuter safely above the trams and bikes, until they crash down on the brick sidewalks. Finally I believe two gentleman own cars, but they rarely drive them because they are afraid.
The Swedish Chef is President
Don’t be an idiot. Sweden has a Prime Minister, not a President.
With that out of the way, we can properly concentrate on my time at eLabs. I promised yesterday I’d document stand-ups the eLabs way, and I’m glad I did because today I got to see first-hand day 2. Standups at eLabs go something like this - everybody stands up from all projects. There’s about 8 employees, so it’s sizeable but not gigantic. On Mondays everybody gives an update for the project they are on. The rest of the week everybody just pipes up if they have a problem. What I find interesting is there is no customer involvement - these stand ups are for team members to team members - and the multiple project nature of the meetings doesn’t seem to slow them down at all.
From there they retire to pairing stations and it’s a lot quieter than the 8th Light office - especially since I’m not at the 8th Light office making noise. They have offices where the pairs work, which I find both good and bad. At 8th Light on fridays we have frequent problems where one pair is on a conference call and another is animatedly discussing a problem, so that would be helpful, on the other hand there’s definitely an energy to everybody in the same room that isn’t there when offices have doors. It’s an interesting hybrid approach, and I could get used to it.
On a personal level I wasn’t 100% today. I woke up at 4:45, apparently Jet Lagged, and learned that Gothenburg doesn’t have early morning coffee shops for iPhone hacking. After walking around the rather cold town for over an hour I finally found one at 7:30, and thought I was fine. At two I crashed, and was completely losing concentration, practically falling asleep in my chair. Fortunately they have ping pong and after a couple quick games I was back to my normal self, and really wrote some code. I really want to get better at JQuery and ScrewUnit, because right now I’m still coding too much Javascript by luck.
Afterwards Jonas was kind enough to join me for dinner and we had a lively conversation about mocks and when (or when to not) use them, as well as the way eLabs does their Rails testing. I’m too tired to properly write my thoughts now, but it’s definitely gonna be a blog post tomorrow. It was a very nice dinner and I’m glad Jonas joined me. Now if you’ll excuse me I have to dodge the death trams on my way back to Andres Apartment.
International Craftsman Swap Day 1
by: eric | June 21st, 2010 | 0 comments »
Today was day one of my Craftsmanswap with eLabs developer Anders Tornqvist, and so far they have treated me with the hospitality and graciousness I expected. Largely they’ve been led by my pair, pictured at right. This is Pixie, who’s been working in the same room as me all day, and when she hasn’t been barking at me she’s been growling. It’s been a tad….terrifying? Especially when the blood is dripping from her teeth, and she can leap so high!
Actually poor Pixie had a rough time of it last night, and it apparently led to her being out of sorts. She eventually got along with me just fine, and I was able to have a productive day pairing with Ingemar. I hope I was helpful, as I’m trying to spend most of my time listening. I hate being the guy who shows up on a project and immediately tells people how to do stuff, plus Ingemar had a grumpy boxer/pit-bull mix next to him so I wasn’t gonna ruffle feathers. The problem with that approach is that you can end up failing to contribute by being too passive, but I think I did okay today. Tomorrow I’ll probably be a little more vocal, and moreso the next day. You know, just in time for me to leave.
The highlight of our day, for me anyway, was implementing drag and drop in JQuery. I’ve never done it before - I think I’ve done it in Prototype but it’s been a while - and it’s amazing what a breeze it was. I’m going to have to find an excuse to use JQuery more, and I’ll probably try and find out some info on ScrewUnit. Of course on the plane I started reading “Growing Object Oriented Software, Guided by Tests” and a new iPhone book, so I’m nothing if not capable of overbooking myself. Speaking of which GOOS looks like a real winner, if you didn’t already know.
In addition to some JQuery at one point or another Ingemar touched on a gem or idiom I wasn’t familiar with, often with me hurriedly scribbling notes probably without him realizing it. The list of gems from today alone was:
- formtastic
- hitch
- machinist
- launchy
- carrierwave
Hitch was seriously cool, allowing us to push git changes as a pair. Formtastic is an interesting form builder, and although we had some struggles with it today Ingemar assures me it’s awesome. It did have a nice DSL syntax. We used machinist’s blueprint feature for building factory objects, kinda like factory girl. I admit I like the concise syntax, but I wonder if we should be making it easier to create lots of objects in setup for a test. Launchy cleanly launched the browser when testing at a given point, and finally I’m excited to use carrierwave for file uploads tomorrow.
I have more notes, particularly regarding the different way that eLabs does standups, but I fear this blog post has become disjointed and a tad dull, so I shall leave you until tomorrow.
TDD in education, they're doing it wrong
by: eric | April 9th, 2010 | 4 comments »
This blog post originally appeared on a blog I maintain for my current game development class. Generally speaking my posts over there are pretty specific to the classes I’m taking, and aren’t appropriate for this blog. Recently however my instructor, who is an extremely smart and accomplished developer in the game development industry, described a common misconception about TDD that prompted me to rant on that blog. Since the subject is TDD I’m placing it here, edited to make more sense.
Recently in class our professor said something like this, “TDD says you should only write the simplest code that can possibly pass the test, and that leads to spaghetti code with a lof conditional logic.” Sadly this left me shaking my head. I’ve been doing TDD every single day for the last 3 years professionally, and intermittently for 2 years before that, and I can say for certain that TDD never caused me to write spaghetti code. Of course I’ve written spaghetti code, including some of the code I TDD’d for the previous class (I’m not real happy with my memory system) but that wasn’t caused by TDD. The crux of the professor’s argument seems to come from a mistaken understanding of TDD. He seems to have TDD as a three step process:
- Write the test
- Write the smallest amount of code to make the test pass
- Repeat
Unfortunately it’s missing a crucial step – refactor! Yes we initially write the simplest code that can possibly pass, but we don’t leave it that way. We write that simple code so we can refactor with a green bar, something that unfortunately my professor doesn’t understand.
When I write the minimal amount of code refactoring becomes easier, because I have a suite of passing tests. In school students and teachers throw around the term refactoring a lot, but are usually unaware that when Martin Fowler wrote the book on Refactoring, defining it for the software development community, he required unit tests. You can’t guarantee your behavior did not change unless you have tests around the behavior, which is why I hear so many students say things like “I’m almost done refactoring but the code doesn’t build yet.” Refactoring is meant to be small steps, in a definite process, so that at the end of each refactoring (such as extract method) I have the same behavior as before, but better code. Most people who refactor don’t have tests, take huge steps and eventually end up hacking and slashing something back together that is close to (but not the same) as their original behavior. That’s not refactoring, that’s hacking - and most students clearly don’t know the difference.
At this point the blog went into a description of how you’re supposed to do TDD, but if you’re reading this blog you probably already know how to do that. The point of moving this here is to point out that TDD is making inroads at the university level, but it has a long way to go. Those doing TDD are a distinct minority, those that are are doing it wrong, and they’re getting bad information. Furthermore let’s remember these are smart people. The professor for my class is frakking brilliant, and the students are amongst the best in the university, and yet in spite of that when they start their first job they’ll do so without writing unit tests. The good news is that smart people are trying out TDD, in an industry (games) that is notoriously slow to adopt software development methodologies, so we are winning. It’s just taking longer than we thought.
Stubbing :new Considered Harmful
by: eric | February 8th, 2010 | 1 comments »
Hi my name is Eric, and I have made a mess.
There I said it. I’m not proud of it, but I believe a couple very loosely related things:
- You only learn from your mistakes
- Everybody makes mistakes, a craftsman cleans them up.
It is in the process of cleaning up the mess that I’ve been trying to evaluate the messy code in the first place. How is the code messy? Was it Test-Driven? It was - or at least it attempted to be (we’ll get back to that). Was I lazy? Certainly not. Am I stupid? Crap I hope not. So how did we end up in this mess?
What’s the mess nimrod?
Recently Justin, our latest apprentice, wrote about attending a code review here. The feature he is referring to is part of one of our best client’s systems, where we integrated with several webservices, making them look seamless in our application. This was an extremely difficult problem, and our code bent in a dozen painful ways for a solution, and has since become rigid. Changes have stopped being done in the nice Test-Code-Refactor mode, and instead are being done by trying a change, trying the product, then backing out the change and making the test pass. While we identified several ways to improve the code, such as better naming and adding a facade between some of our interfaces, one stated goal was to “make the tests readable.” See the problem isn’t that it’s not tested - it’s that you can’t follow the tests at all. Let’s look at an example, modified to protect the guilty:
- it "should call a webservice when its complete" do
- @caller.should_receive(:call_webservice)
- typedObj = mock("Obj", :no_follow_ups? => false, :null_object => true)
- ProprietaryObject.stub!(:create_typed_obj).and_return(typedObj)
- @page.stub!(:widget_id).and_return(@widget.id)
- @page.stub!(:previous_page_id).and_return(nil)
- @product.page_cache = [@page]
- @widget.follow_ups({}, {:application_id => "123", :group => "group"})
- end
-
This probably isn’t the worst example - if you look closely you can see that we’re testing that call_webservice needs to get called when ‘its complete.’ But what complete? I don’t see a stubbed object that returns complete. Also I have no idea what @page, @widget, @product or :createtypedobj are doing here. When I want to write the next test I have to guess at intent, and start playing with variables. What this is trying to test is that a webservice caller object receives call_webservice when the widget (an object on the screen) is called with certain variables. I’d tell you what those variables are, but I truly don’t know.
It doesn’t get better. Let’s look at where some of those variables are coming from. These are excerpts from a setup method that is too long.*
- Context.stub!(:find_by_widget_and_application_form).and_return(@context)
- Page.stub!(:new).and_return(@page)
- ...
- @caller = mock('caller', :call_webservice => nil)
- WebserviceCaller.stub!(:new).and_return(@caller)
- ...
- @page_factory = mock_model(PageFactory, :acquire => @page)
- PageFactory.stub!(:new).and_return(@page_factory)
-
So by my count we’ve stubbed new three times, two finders, and an acquire all of which inject yet another dependency into the code. Thus the premise of the article stubbing new considered harmful.
Is it really harmful?
Dependencies in static languages are generally more onerous than what we’ve got here, sometimes extremely painful although usually it can be accomplished with simple setters and constructors. In Ruby this isn’t the case - you can just stub new and create the object the way the user intended, thereby continuing to test. This can be a VERY BAD THING because it’s a moment where you need to pause. Do you need this dependency? Should you be wrapping dependencies? Do you need a facade or wrapper object for a couple dependencies? The difficulty of DI in other languages enforces that pause, but Ruby does not. It lets you stub anything, only to one day wonder why you have such a mess on your hands.
It’s important to remember that Dependency Inversion existed before Unit Testing, and isn’t just a Unit Testing technique. Indeed we often sell TDD as a way to make you have better designs, and yet here it failed me because I can so simply call new and continue testing. This is a mistake. To paraphrase Jurassic Park, just because you can easily stub new doesn’t mean you should. Would you create a constructor that took five objects? Then why would you stub :new (or finders, or factory methods) five times. Would you pass in an object to the constructor that’s only used in one method? No - that’s not cohesive. By stubbing :new you can slowly, and easily, introduce dependency after dependency creating an indecipherable mess despite writing tests. Worse you can do this easily, without suffering the traditional pain of tightly coupled code. It’s only later that you’ll feel the awful, horrible, indescribable pain. Trust me it’s bad.
Am I really advocating stopping stubbing :new? No not really. It makes perfect since to just call :new when you can, and in many cases factories are a way to get around the limitations of a static language. What I am saying is that each time you do stub!(:new) THINK! You have a dependency to manage, so manage it. It’s your job you know.
*This is also a smell. Allow me to quote “The Art of Unit Testing”, an excellent book on Unit Testing by Roy Osherove
Don’t use [SetUp] and [TearDown] to initialize or destroy objects that aren’t shared throughout the test class in all the tests, because it makes the tests less understandable. Someone reading your code won’t know which tests use the logic inside the setup method and which don’t.
We're Busy!
by: eric | August 23rd, 2009 | 0 comments »
This week is a big one for the 8th Light team. Let’s head through the highlights:
Agile 2009
As usual a large number of 8th Lighters will be participating at Agile 2009. This is always a fun and educational experience for us, and this year it’s in our hometown. Let’s go through the talks we’re giving:
Mission Impossible: TDD and Javascript In the New Orleans room on Tuesday at 11:00 Jim Suchy will be giving a talk on doing TDD in Javascript. Javascript is a language that people tend to claim is “untestable” or “not worth it” but Jim will be showing that testing is not only possible, but worthwhile. In addition he demonstrates some of the neat features that make Javascript a cool language.
Ruby Kata and Sparring Back in the New Orleans room on Thursday at 9:45, Micah Martin will be talking about Ruby Kata and Sparring. Everybody wants to be a great developer, but how do you do it? Micah will show two different practice techniques, kata’s and sparring. If you go to this talk you get to judge the speaker and tell him how well he codes. How often do you get to do that?
TDD on iPhone The Eric’s are giving their legendary talk on practicing TDD on the iPhone on Thursday from 2:00 - 3:30 in Grand Ballroom F. This time we have a special surprise for those who attend - a Randori coding session where you will code functioning iPhone application. Please wash your hands before attending, as you’ll be using my keyboard. Head to my github page to see a sneak preview of what we’ll be working on.
Live Aid Once again some 8th Light guys will be helping out with Live Aid, including our newest Craftsman Colin Jones. Come to the stage, write some Rails, help charity. 10 minutes or 10 hours it doesn’t matter. Experience in Rails or even web development are unnecessary - that’s what the mentors are there for.
chiPhone
The second meeting of chiPhone, the Chicago iPhone developer group, will be held at a special location this week: the Obtiva offices! Thursday night if you’d like to do some hacking head to the chiPhone website to register - or just show up. I only need to count so I order the right amount of pizza.
SCNA America
I saved the best for last. Software Craftsmanship North America is a joint effort by 8th Light and Obtiva and frankly it has the best speaker lineup I’ve ever seen. Registrations are still available and cheap! If I could take credit for this I would - but it really goes to the organizers, who did a fantastic job. The entire 8th Light staff well be there and available for discussion, questions, and to accept free beer from the attendees. Meanwhile two of us will be speaking:
The Business of Craftsmanship “Craftsmanship sounds expensive!” If you’ve heard similar comments from your supervisors or clients, then join Micah, Kevin Taylor and Carl Erickson, three experienced craftsmen-turned-entrepreneurs for this 30 minute panel discussion. All three panelists come from technical backgrounds and have built successful software development companies that are built on craftsmanship values, such as quality, learning, and community, and use Extreme Programming practices to develop software.
Apprenticing to Mastery Listen to Paul and Obtiva’s Dave Hoover discuss how an Apprenticeship program can benefit your company and your career. Software companies are always looking for ways to develop skilled developers. Formal software apprenticeship is the approach taken by more and more companies, including Obtiva and 8th Light. Over the past 2 years we have observed almost a dozen apprenticeships and come to recognize certain apprenticeships of developers that are themed by their aspiration to mastery.
This might be the biggest week in 8th Light history - hope to see you there!
Announcing chiPhone
by: eric | July 9th, 2009 | 0 comments »
It’s with great pleasure that I announce the creation of chiPhone, the Chicago iPhone developer’s group, with our first meeting on July 23rd at 6:30. The fourth Thursday of every month should feature interesting presentations, hackfests, and everything else you’d expect from a quality developer group.
The group website is now up and running at www.chiphonegroup.org where you can register there to attend the first meetup. In addition you’ll find directions to the 8th Light offices, where most of our meetings will take place, and the announcement of the topic for the next meeting. As the official site website all further information will be posted there, including video recording of the talks.
The first meeting will feature a presentation by “the Eric’s” on Test Driven Development for the iPhone. We’ll be starting with the basics of setup and work all the way through Dependency Injection using Interface Builder. Bring your Macs so you can grab our github project for experimenting. Get to the 8th Light offices early for pizza and refreshments.
8th Light is located just off of Route 45 in Libertyville, and detailed directions are available on the chiPhone website. In addition we are near the Libertyville train station, just email me if you need to arrange to be picked up.
I’m looking forward to a lot of great meetups, and I’ll be asking you to provide some topics in the near future.
TDD and iPhone - NSTimer
by: eric | May 11th, 2009 | 3 comments »
TDD on the iPhone is a challenging experience, especially when you’ve been spoiled by Ruby like I have been, but it can be done. I have a tutorial in the works for getting started, but in the meantime I’ll be writing bits and pieces about my experience. The first was here and this is the second. Test cases are written using the Google Toolbox for Mac. This particular example is about the NSTimer.
It keeps going and going
The app to your right is a simple app for experimentation purposes that runs Conway’s Game of Life. It has two buttons: advance and start. Advance moves one generation ahead each time you press it, whereas Start keeps advancing generations until you touch Stop. To implement that we use an NSTimer object which is programmed to call advance on the game object. The design is simple, shown here:
The GameRunner creates an NSTimer, the NSTimer sends the message to Game. Great but how do we test it? The less I know about something the more I tend to test it, which means I tend to write smaller and smaller tests. Let’s look at my first few tests of the GameRunner object:
- -(void) testSetsAndGetsTimeInterval {
- runner.interval = 0.30;
- STAssertEquals(0.30, runner.interval, nil);
- }
- -(void) testCreatesNSTimerObject {
- [runner start];
- STAssertNotNil(runner.timer, @"The timer was not created");
- STAssertTrue([runner.timer isValid], nil);
- }
- -(void) testNSTimerFields {
- runner.interval = (NSTimeInterval) 0.26;
- [runner start];
- STAssertEquals([runner.timer timeInterval], 0.26, nil);
- }
We’ve got some basic tests of creation. At this point I was stumped. I couldn’t check the other parameters of the timer, because they weren’t public variables, so at this point the code that actually created the timer looked like this:
- -(void) start {
- timer = [[NSTimer timerWithTimeInterval: interval
- target:nil
- selector:nil
- userInfo:nil
- repeats:true] retain];
- }
That doesn’t really help me does it? I have a timer with an interval, but it won’t call anything when it’s triggered. This is about the time I got to pair with Jake Scruggs during the Craftsman Swap, which he’s written about here. It went badly, somewhat embarrassingly for me since I’m supposed to be the expert, however we learn from failure. Let’s look at some of the steps Jake and I took that didn’t quite get us there.
The first pass on the test was simple. We needed a mock game, and it needed to have its advanceGeneration method called (Ed. note: I realize they aren’t called methods in Obj-C, to which I say: bite me.) each turn. Let’s try the brute force approach:
- -(void) testTimerCallsGameAdvance {
- MockGame *mockGame = [[MockGame alloc] init];
- runner.game = mockGame;
- [runner start];
- sleep(.30);
- STAssertTrue([mockGame advanceGenerationCalled], nil);
- }
I’m writing the original tests from memory, so I make the occasional error here, but it doesn’t matter since we got this wrong. This test here seemed the most logical. We ran the test and it failed, yea! Then we updated the code:
- -(void) start {
- timer = [[NSTimer timerWithTimeInterval: interval
- target:game
- selector:@selector(advanceGeneration)
- userInfo:nil
- repeats:true] retain];
- }
Experienced Cocoa developer’s have already discovered our error, please don’t ruin it for the rest of the readers. So after changing the code we run the test and…we fail. So from here Jake and I figured it out. Sleep won’t work because it stops the entire application, including the run loop that calls our timer, so we’ll just have to get the info out of the timer another way. We’re interested in testing that we’ve setup the timer correctly, and can trust that the timer just works. After a loooong time browsing documentation we figured it out. We could call this:
- -(void) testTimerCallsGameAdvance {
- MockGame *mockGame = [[MockGame alloc] init];
- runner.game = mockGame;
- [runner start];
- [runner.timer fire];
- STAssertTrue([mockGame advanceGenerationCalled], nil);
- }
This will fire the timer and validate that it is setup correctly. So we did this, our test passed, we ran the app and it….failed. We knew the timer was executing because our test was passing, but when we ran the real app it just didn’t do it. Stumped and frustrated we stopped for the day. Then time passed…..
Yesterday I had a candidate in for an apprenticeship position, and we attempted to solve the same problem. We re-evaluated the test and decided calling fire directly was cheating. We looked into a half-dozen other ways to test this and learned about the NSRunLoop. Too much coding in Windows had rotted my brain, the run loop in Objective-C is not the same as the one in Windows. Specifically the current run loop is accessible as an object. We wrote a new test:
- -(void) testTimerCallsGameAdvance {
- MockGame *mockGame = [[MockGame alloc] init];
- runner.game = mockGame;
- [runner start];
- [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.30]];
- STAssertTrue([mockGame advanceGenerationCalled], nil);
- }
It’s not perfect - the 0.30 relies on the hard coded default interval of 0.25, and that is too long, but it failed! In the process of learning about NSRunLoop we also realized I used the wrong method. The working code is this:
- -(void) start {
- timer = [[NSTimer scheduledTimerWithTimeInterval: interval
- target:game
- selector:@selector(advanceGeneration)
- userInfo:nil
- repeats:true] retain];
- }
See the word “scheduled” in front of Timer? That actually adds the timer to the default run loop. Now we ran our spec, ran our actual code, and it works! The moral of the story? Well if you’re persistent enough you can get your code under test, and if your test is correct then your code will work.
Dependency Inversion Principle and iPhone
by: eric | April 16th, 2009 | 0 comments »
Vertical Dependency
While working on the slides for our upcoming* talk on TDD for iPhone I asked Eric Meyer why we need the Dependency Inversion Principle. He eagerly answered, “Testing!” which made me laugh because I wasn’t giving him a trivia quiz, and I love Eric’s enthusiasm. He’s right, but the answer is circular. TDD is great because it gives us better designs that correspond to the DIP which enables TDD. Ha! I win, would you like to buy my consulting services? I have plenty of three letter acronyms where those came from.
Fortunately this isn’t the case, as the DIP existed well before TDD was popularized, but recently there was a bit of a dust-up over the SOLID principles. Many developers don’t understand why dependency inversion is important, so let’s demonstrate the usefulness in the Objective-C language on the iPhone.
The Dependency Inversion Principle (DIP) reads as follows:
A. High level modules should not depend upon low level modules. Both should depend upon abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions.
So your code should depend on interfaces not on concrete classes, but why? Let’s look at a useful example in the Objective-C built in classes.
- [NSString stringWithFormat:@"Object is: %@", object];
Do you see the DIP at work? It’s subtle here, but look at the method stringWithFormat, which takes a format string and then a list of parameters to fill in the format specifiers. The format specifier here is “%@” which takes any Objective-C object and calls descriptionWithLocale on it, or description otherwise. The object that is passed in here could be anything because all the stringWithFormat method cares about is that the object provides at least one of the two methods above. It’s depending on the interface, and not the concrete class. Let’s imagine a world where this didn’t exist, and the NSString method could only be composed of other strings. Suddenly you’d have something like:
- return [NSString stringWithFormat:@"Object is %s", [object toString]];
That’s not bad at all is it? Well what if there are different objects.
- return [NSString stringWithFormat:@"Object is %s %s %s", [object1 toString],
- [object2 toS],
- [object3 stringify]];
Are you starting to see the problem? Suddenly I can’t use this method without being cognizant of the specifics of the object I passed in. The minute one of these interfaces changes I have to change my code. I stole this method from some real code, so let’s look at it with some context. Once upon a time I was writing a mock object for an iPhone application. Now iPhone doesn’t have a good mock object framework, at least that I’m aware of, so I was rolling my own mock. The mock logged calls to it which I then queried. To construct the string I used this method:
- +(NSString *) createStringFrom: (id) cell at: (CGPoint) point
- sizeOf: (CGRect) rect
- {
- return [NSString stringWithFormat:@"%@ %f %f %f %f", cell,
- point.x,
- point.y,
- rect.size.width,
- rect.size.height];
- }
Don’t sweat the details right now, they’re not important. Instead look at how you can see the DIP succeeding and failing in the same code here. The first parameter to createStringFrom is a cell object, but it’s of type id, so it could really be anything. That’s good because I wasn’t sure when I wrote this mock what type the cell would be and I’d generally prefer that my mock object not have to know the details. In fact the cell did change type several times which is why insulating yourself from change is so important. There’s an assumption by many developers that you should only worry about the things you’ll be changing in the future, but the best gauge of future changes is present changes, and if you’re changing a module frequently during development as you get it right you’ve found a likely change point. Even if you haven’t, you’ll make your life simpler in the present by insulating yourself from that change, speeding up your development cycles. I digress.
The rest of this method isn’t so lucky. You see CGPoint and CGRect are C structures, and I am left to write these as floats in the string (%f). If I was to change the parameter types frequently I would probably introduce some way to insulate myself from that change as well, possibly by wrapping them in objects. Since those parameters have not changed I haven’t done that, although I’m thinking about it.
Our current apprentice Colin has given a first-hand account of refactoring to DIP here as well.
How do I do it?
Eric and I are working on a program to run Conway’s Game of Life. On the iPhone screen you see Rounded Rect Buttons that change color based on whether a cell is alive or dead. The problem is that we don’t really want to drag and drop 300+ tiny buttons on the screen with interface builder. Instead we want to create them programatically, when the GameOfLifeViewController is loaded. Again I don’t want to overload you with extraneous details, so just take my word for it that there is a GameOfLifeViewController, and it needs to generate buttons. Here’s what my first pass at a test looked like in rough pseudocode:
- for (int row = 0; row < 15; row++)
- {
- for (int column = 0; column < 15; column++)
- {
- button = GetButtonViewAt(row, column)
- STAssertEquals(expectedSize, button.size)
- STAssertEquals(expectedLocation, button.location)
- STAssertAction(expectedAction, button.action)
- }
- }
There’s a lot wrong with this test. The most obvious is the hard coded 15. What happens when we want to change the number of rows and columns? Now we have to change code in multiple places. Naturally we did in fact change this, so I would have paid for this decision quickly if I hadn’t already refactored it away. The second is that there’s going to be more than one test for creation, each of which will have to perform the same 15x15 loop. The annoyance of constantly changing this will reveal the root the problem, the GameOfLifeViewController should really only be in charge of GameOfLifeView and really doesn’t need to know the details of the creation of its subviews. It’s violating the Single Responsibility Principle. We can fix that with a factory object, and will do so, but that will violate the Dependency Inversion Principle. So we’ve got one DIP violation, an SRP violation, and a potential second DIP violation, all demonstrated in 6 lines of test code.
Fortunately we’re going to introduce some interfaces to clean that up. The first is an interface to the board object. Why the board? Well the board should know the number of rows and columns it has, and if we can inject a fake version of the board we can actually set those to be 1 and 1. That’s will make our test focus on what we are truly concerned about. The second thing we’re going to do is introduce the Abstract Factory pattern to create our button views. It’s a bit of a heavyweight solution but its going to pay off by cleaning up our client code dramatically. We’ll have a View Controller concerned with controlling the view, and a creation factory concerned with creation, as well as a board that keeps track of rows. Let’s take a look at the test now, again in rough pseudocode.
- -(void) setUp
- {
- controller = [[GameOfLifeViewController alloc] init];
- controller.board = [[MockBoard alloc] init];
- controller.buttonControllerFactory = [[MockButtonFactory alloc] init];
- }
- -(void) testCreationOfButtons
- {
- [controller viewDidLoad];
- bool called = [controller.board calledWith: params that: I want: true];
- STAssertTrue(called);
- }
So what’s going on here? In the setup we load up the board with a fake board, one that returns 1 for its rows and columns, and we load up its buttonControllerFactory with a fake buttonController Factory. In our test we call the viewDidLoad method, which is called on controllers after their view is loaded. Duh. That’s the method where we use the buttonControllerFactory. Then we call a method on the mock factory calledWith: that takes the parameters I expected the creation factory to receive. Finally we check that it was called with the assertion. So far I’ve only been showing test code, because I wanted to demonstrate just how much cleaner our tests have become. Now there’s no loop, no hard coded constants, and no testing the internals of the creation factory in the view controller. That isn’t to say we don’t test the creation, we just do that in a different test case, the one that corresponds to the ConcreteButtonFactory class. As a rule if our test code is cleaner, our implemenation code is cleaner, and that’s the case here as well.
Let’s now look at the real class, and how to enable Dependency Inversion on it. We have to start with Objective-C protocols. Protocols are very similar to Java interfaces, and just as useful, but are strangely underrepresented in XCode. As best I can tell** just create an NSObject subclass and remove the .m file and any imports from the .h. Here’s the protocol from the unfortunately named ButtonControllerFactoryProtocol.h:
- #import "ButtonController.h"
- @protocol ButtonControllerFactoryProtocol
- -(ButtonController*) createButtonControllerForCell: (id) cell
- at: (CGPoint) point
- sizeOf: (CGRect) rect;
- @end
As you can see the interface only defines one message, createButtonControllerForCell. It returns the ButtonController object, although it could return an object conforming to a protocol. Indeed one could argue it should, as that would streamline my mock object. Hmmm… I see a refactoring in my future. Now let’s look at the class definition for the ConcreteButtonControllerFactory, which is the object that is actually used when the real app is running.
- #import <uikit />
- #import "ButtonController.h"
- #import "ButtonControllerFactoryProtocol.h"
- @interface ConcreteButtonControllerFactory :
- NSObject<buttoncontrollerfactoryprotocol> {
- }
- @end
Not much here is there. The important part to look at is NSObject
- #import "ConcreteButtonControllerFactory.h"
- @implementation ConcreteButtonControllerFactory
- -(ButtonController*) createButtonControllerForCell: (id) cell
- at: (CGPoint) point
- sizeOf: (CGRect) rect;
- {
- ButtonController *controller =
- [[ButtonController alloc] initWithCell:cell];
- UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
- [button setFrame:rect];
- [button setCenter:point];
- [button setImage:[UIImage imageNamed:@"dead_cell.png"]
- forState:UIControlStateNormal];
- [button addTarget:controller
- action:@selector(bringToLife:)
- forControlEvents:UIControlEventTouchUpInside];
- controller.view = button;
- return controller;
- }
- @end
This isn’t an article on UIKit so I’m not going to get into the details of creating the button. You can see again that I’ve ignored the DIP for creating the UIButton and the ButtonController. Since this is a factory I’m okay with this violation. I could have created abstract factories for the UIButton and ButtonController and passed them in here but I don’t believe I’d gain any benefit from that implementation. That’s verified by my testing, as writing tests for the creation of these objects was hard before I introduced this factory but isn’t any longer. If it becomes difficult then I’ll consider making the change to two factories. Now we need to inject the concrete dependency. In a Java project you could do this in a main method or with a DI framework like Spring. We’re going to be using my favorite DI framework of all time: Interface Builder!*
It’s a common misconception that IB is just a GUI builder. What’s great about it is that it doesn’t just generate a bunch of code, but instead “freeze dries” real objects to be instantiated when the program loads the NIB file. Furthermore while the most common Outlets are UI elements there’s no reason other objects can’t be used. Let’s take a look at my NIB document window for the GameOfLifeViewController:
As you can see I’ve got objects for the Game, ConcreteButtonControllerFactory, and the Board. That’s because all three of the objects are injected at runtime, while the code depends on protocols. To add your own objects to a NIB file simply by selecting it from the Library:
It’s inspector window will have a class drop down, so set this object’s object to your class. Finally you need to connect the outlets to actual outlets in your code. Let’s look at the Outlets tab in IB for my controller (the File’s Owner):
Notice how the controller still thinks of them all as NSObject? So if I change the objects it doesn’t care, as long as I conform to the interface? Finally let’s take a peek at the controller interface file:
- #import "BoardProtocol.h"
- #import "ButtonControllerFactoryProtocol.h"
- #import "GameProtocol.h"
- @interface GameOfLifeViewController : UIViewController {
- IBOutlet NSObject<boardprotocol> *board;
- IBOutlet NSObject<buttoncontrollerfactoryprotocol> *buttonFactory;
- IBOutlet NSObject<gameprotocol> *game;
- }
- @property(nonatomic, retain) NSObject<boardprotocol> *board;
- @property(nonatomic, retain) NSObject<buttoncontrollerfactoryprotocol> *buttonFactory;
- @property(nonatomic, retain) NSObject<gameprotocol> *game;
See any dependencies on the actual objects? Nope - just protocols. There are properties for the objects so that I can inject the dependencies through the tests, all of which pass in fake versions as various times depending on how it suits the test. It may be unhealthy - but I find this incredibly cool.
Summary
What I love about Interface Builder is setting this up is extremely simple. Writing tests for the controller that is based on these dependencies is also extremely simple, far simpler than just depending on the concrete objects. It’s funny how developers often complain about the time wasted writing tests or “over-engineering” in this way, but once I broke these dependencies I got things done a lot faster. I’m writing working code without loading the actual simulator. I write my tests first, making progress, and when I’m done for the session I run the app once or twice just to verify I haven’t done anything like forgotten to inject the dependency. Compare that to running the simulator constantly, each time hoping your code is functional. Who’s wasting their time now?
FootNotes:
* Uh yeah we gave that talk already. These take a while!
** I’m 99% positive there’s a better way, and that I haven’t found it. Tell me if there is!
*** To be fair it’s the only one I’ve actually used.
Selenium on Rails Released
by: eric | March 7th, 2009 | 0 comments »
Quick announcement, Selenium on Rails has been released, now supporting Rails 2.2 and with the latest Selenium Core. Numerous bug fixes are in this release as well, thanks to commiters Marcos Tapajós, Nando Vieria, and Gordon McCreight.

To update to the latest version install the plugin from http://svn.openqa.org/svn/selenium-on-rails/stable/selenium-on-rails. This release is once again not compatible with previous versions of Rails, so check the website to install new revisions.
I also want to add a new patch policy. To patch/contribute to selenium on rails head to the http://github.com/paytonrules/selenium-on-rails and fork the repo, then just issue a pull request. I will not be taking patches that don’t have tests however, as it is just too much work for me to retrofit tests on to the patch.
For any questions or comments contact me at eric (at) 8thlight (dot) com. Look for me at SDWest and Scotland on Rails.
When is a Mock not a Mock
by: eric | January 10th, 2009 | 0 comments »
A couple of weeks ago I had to add a feature to some code that was written almost two years ago. It was a pretty simple web service client that constructed some XML, using Ruby’s REXML library, and made the web service call via another library. A quick inventory shows two dependencies, the web service call and REXML, so that’s what I expected to see when I came across the tests. But what did I see? Paraphrasing:
- @client_under_test = Client.new
- @client_under_test.stub!(:send_message)
- @client_under_test.stub!(:parse_response)
Of course the send_message call contained the construction of the XML so that there was no test that the XML being constructed was correct. Heck that was all that was being done in the class, and a closer inspection of the tests revealed that all they were doing was testing the error handling by changing the return value of parse_response. This is a classic sign that the developer at the time couldn’t figure out how to stub out the actual dependency, and so they did the next best thing, they stubbed out the caller.
I knew this was wrong, but I had an iteration meeting the next day and still had to update the .NET web service that this code was calling. So I started to just go ahead and make the untested change, but then my Clean Code wristband started burning until I couldn’t take it any more. I had to get the REXML library under test. So what to do? Well the REXML construction looked like this:
- doc = REXML::Document.new(create_schema)
- doc.elements["name1"].text = "thing 1"
- doc.elements["name2"].text = "thing 2"
- ...
Okay I know how to do this normally. The first test was simple:
- REXML::Document.should_receive(:new).with(schema)
It passed! What was so hard about testing this anyway? Okay let’s test that the elements are set:
- ....
- elements = mock(REXML::Document, :[] => mock_element)
- doc = mock(REXML::Document, :elements => elements)
- REXML::Document.stub!(:new).with(schema).and_return(doc)
- ...
Oh that sucks! Since the API doesn’t run entirely through the doc object I have to stub elements, then stub each individual element, then should_receive on text, and if I want to be perfect I can stub out the array accessor too. I have to should_receive for each element name, the tests will be hard to follow and fragile. Now I get why the original developer punted on this. There’s got to be a better way. I can start expecting actual XML, but from past experience I know that leads to very hard to read tests that give errors that aren’t easy to diagnose. What I really care about is that the elements in this hash-like structure have their text element set to the right data. After trying out several approaches I had a moment of inspiration, I want a struct! Must be my inner C programmer. If elements was a hash of structs, I could just check their text values are set. This way I’m testing that I’m using the REXML library right rather than testing the library itself. If only Ruby had a struct concept…..
I suppose you’ve already figured out that it does, haven’t you?
- MockElement = Struct.new("MockElement", :text)
What that does is setup a class named MockElement, with the accessor text. When is a Mock not a Mock? When it’s really a Fake. Instead of stubbing out elements to return yet another mock, elements will return a hash of the element names I know I’m using that point to these fake elements. Then after making the call in the client, I’ll just check that the text is set properly. This is best demonstrated with an example:
- before(:each) do
- @elements = initial_elements_hash
- @doc = mock(REXML::Document, :elements => @elements)
- REXML::Document.stub!(:new).with(schema).and_return(@doc)
- end
- def initial_elements_hash
- return {"element1" => MockElement.new,
- "element2" => MockElement.new}
- end
- it "should set the data in the xml doc" do
- @client.send_message
- @doc.elements["element1"].text.should == "Eric"
- @doc.elements["element2"].text.should == "Smith"
- end
Aha! Now I’ve tested that the XML was properly constructed without relying on looking at the actual XML text itself and without stubbing out the class itself. The code is cleaner, the tests are easier to understand, and I can implement my new feature. More importantly, my wristband stopped burning.
Selenium on Rails example
by: eric | September 20th, 2008 | 0 comments »
The files for the WindyCityRails talk here.
Selenium on Rails released
by: eric | September 14th, 2008 | 1 comments »
Remember when I used to post here? Not that I’ve ever been prolific but there is a reason I haven’t posted in 53 days, well at least the last 30, as I’ve been hard at work preparing for my Selenium on Rails talk at Windy City Rails. What work? Primarily releasing a new version, one that works on Rails 2.1. These are the newest features:
- Did I mention it works in Rails 2.1? (Thanks to Ryan Bates)
- Checkout/run tests is now possible. You DON’T have to put this in the vendor/rails directory of an existing project.
- Your config file is now stored in config/selenium.yml, so you can store it in source control. Thanks again to Ryan
During the last month I’ve taken the official repository at OpenQA and cloned it at git. While I’ll still be maintaining the OpenQA version because I like the association with the group, I find it’s hard to get help with contributions on the site through their subversion repository. Therefore I’ve created a github for it that will be periodically synchronized with the subversion repo. If you want to help by contribution features or patches, or you want the latest and greatest repo, head here: http://github.com/paytonrules/selenium-on-rails/tree/master. Otherwise it’s still hosted at its normal location here: http://selenium-on-rails.openqa.org/. There’s still an old version available for Rails users that haven’t upgraded, and the instructions for installation are available as well.
Please let me know if you got feature requests for Selenium On Rails, or patches ready to go. I’m looking forward to revitalizing that project.
Some Random RubyCocoa stuff
by: eric | July 23rd, 2008 | 7 comments »
I went to WWDC last week (1), and while I was there I got a chance to talk to a couple of their engineers and picked up a few things about RubyCocoa. Neither of them are really enough for a blog post on their own, hence the title of this article.
Running tests in XCode
When you’re writing RubyCocoa you may find you have three windows open. XCode to create your files, Interface Builder to design your interface, and Textmate to edit code and run tests. If not Textmate, then probably a command window. To put it politely - this sucks (2). While I’m no big fan of XCode’s text editor I pretty much have to have it open (3) while I’m developing RubyCocoa, so how do I run specs from within XCode? It’s simple. Open up or create a new RubyCocoa project. On the left you should see Targets, click the tree to open it:

You can see the process for building your application here. We’re going to add running specs as a last step, so that our build will fail when our specs do. Right click on the target, and add a new Run Script phase:

Then just add this to the script.

It’s just that simple! I put all my specs in a spec directory, don’t add them to the target of course, and they get run on each build. Here’s an example from a project I’m working on with a failing test:

This shows up in the Build Results window in XCode which you’ll see when you click the worlds tiniest red x in the corner of the screen.

Congrats, now you can code in XCode and not Textmate. Okay it’s text editor is poor, but Interface Builder and XCode are built to work together. For example when you have XCode and Interface Builder open you don’t have to constantly drag-and-drop from finder to IB, it just detects your code changes. This is extremely handy when adding actions or outlets. In fact the two apps are so intertwined Interface Builder just plain doesn’t work that well stand-alone. That’s yet another reason to keep using XCode, no matter how much I dislike it.
Opening a File or Directory in RubyCocoa
My first two tutorials use simple “selectors,” Objective-C’s fancy name for a method. Actually that’s Smalltalk’s name for a method, and Objective-C steals it. To use Smalltalk terms there are unary messages, which are the kind that only take one or 0 parameters, and keyword messages. Keyword messages have named parameters, and ruby doesn’t have named parameters, so how do we send multiple arguments to a method in RubyCocoa? This simple example of opening a directory will demonstrate.
Start by creating a new RubyCocoa project. For directions on the basics go here. We’ll be doing BDD again so I expect you’ll be able to run tests. Call your new project OpenDirectory or something similar, then use the directions above to add a run specs phase to your build process. Now open the MainMenu.nib, and create a window that looks like this:

That’s a lovely dialog. Let’s get started running code. Click on the build and go button. What’s this?

Our build doesn’t work! We don’t have a directory called spec, or any specs in it. Create a spec directory under Create a spec in the spec directory called choose_directory_spec.rb. Remember not to add it to the target, and make sure it is in the specs directory. Here’s our first spec:
require 'choose_directory'
describe ChooseDirectory do
it "should be an NSObject" do
directoryController = ChooseDirectory.new
directoryController.is_a?(OSX::NSObject)
end
end
I know pretty simple. I’m not going to go baby steps through this because at the moment I lack the patience. If you see an error that your build failed because you don’t have a file choose_directory then you’re on the right track. Create the ChooseDirectory class, this time in the root directory and add it to the target. I choose to group my specs in an XCode group called Specs and my classes in the Classes group that’s already provided for you, but those are just groups and you can feel free to do this any way you please. Now let’s look at the next few tests.
def OSX._ignore_ns_override; true; end
before(:each) do
@mock_panel = mock(OSX::NSOpenPanel, :canChooseDirectories= => nil, :canChooseFiles= => nil)
OSX::NSOpenPanel.stub!(:openPanel).and_return(@mock_panel)
@directoryController = ChooseDirectory.new
end
it "should have an action open directory" do
@directoryController.open_directory
end
it "should open a panel" do
OSX::NSOpenPanel.should_receive(:openPanel).and_return(@mock_panel)
@directoryController.open_directory
end
it "should configure it to select directories" do
@mock_panel.should_receive(:canChooseDirectories=).with(true)
@directoryController.open_directory
end
it "should configure it so it can't select files" do
@mock_panel.should_receive(:canChooseFiles=).with(false)
@directoryController.open_directory
end
One thing probably jumps out at you, that big strange command def OSX._ignore_ns_override; true; end If you don’t include this you’ll get warnings that you can’t override the methods in OSX::NSOpenPanel because the arguments don’t match. We didn’t override them of course, we stubbed and mocked them with RSpec, but from Cocoa’s perspective that’s the same thing. We remove the error by monkey-patching _ignore_ns_override to return true. Rucola (4) apparently has this problem licked, otherwise you’ve got to put this before your mocks get loaded. Looking down the specs you can see I’m calling NSOpenPanel class methods, and configuring it. The method openPanel creates an NSOpenPanel object and returns it, the other two methods should be self explanatory. Isn’t it interesting how you can figure out the intent of the code from these tests? It’s almost like a specification. Here’s the code that makes this pass:
ib_action :open_directory
def open_directory
panel = OSX::NSOpenPanel.openPanel
panel.canChooseDirectories = true
panel.canChooseFiles = false
end
One action, open_directory, that sets up the panel. We haven’t displayed the panel yet. Remember what I said about selectors with named parameters? Well here’s where it comes into play. We need to call the beginSheetForDirectory method on that panel. This will display a standard dialog box for opening directories. Here’s the full method signature, from the Objective-C documentation:
- (void)beginSheetForDirectory:(NSString *)absoluteDirectoryPath file:(NSString *)filename types:(NSArray *)fileTypes modalForWindow:(NSWindow *)docWindow modalDelegate:(id)modalDelegate didEndSelector:(SEL)didEndSelector contextInfo:(void *)contextInfo
This is a keyword message. The syntax works like this:
[method name]: [first parameter] [first keyword]: [second parameter]…..forever
So for beginSheetForDirectory that’s one, two, three…oh man that’s a lot of parameters. Here’s what my first attempt at doing this in RubyCocoa looked like (in another application):
beginSheetForDirectory_file_types_modalForWindow_modalDelegate_didEndSelector_contextInfo(nil, nil, nil, nil, self, "open_panel_did_end", nil)
Now that is a method name! Fortunately I found a slightly (5) better way to do it. It looks an awful lot like sending a hash of parameters, something that should be familiar to Rails users. Here comes our next test:
it "should call beginSheetForDirectory" do
@mock_panel.should_receive(:beginSheetForDirectory).with(nil,
:file, nil,
:types, nil,
:modalForWindow, nil,
:modalDelegate, @controller,
:didEndSelector, "open_panel_did_end",
:contextInfo, nil)
@directoryController.open_directory
end
This is closer to the named parameters convention of Objective-C. The panel will call beginSheetForDirectory with nil as the name of the initial directory. The first parameter isn’t named, it’s specified by saying “ForDirectory”. By passing nil we say “open this directory to the same directory I did last time.” Works fine for most situations. Only two of the parameters are really interesting. The first is the modalDelegate, which I’ve specified will be the controller. A message will be sent to the modalDelegate when the panel operation ends. I just want it to send it back to the controller. The second is the didEndSelector which I’ve specified to be the method open_panel_did_end. We’ll come to that method in a minute.
Let’s make that spec pass:
def open_directory
panel = OSX::NSOpenPanel.openPanel
panel.canChooseDirectories = true
panel.canChooseFiles = false
panel.beginSheetForDirectory(nil,
:file, nil,
:types, nil,
:modalForWindow, nil,
:modalDelegate, @directoryController,
:didEndSelector, "open_panel_did_end",
:contextInfo, nil)
end
Pretty simple. That command will display an Open Directory screen. What do we want to do with it when we’re done? That’s where open_panel_did_end comes in. It will be called by Cocoa when the panel is closed. I want to take the directory that was selected by the user, and display it in the text box in our interface.
it "should set the directory name outlet on open_panel_did_end to the directory selected" do
@directory = mock(OSX::NSTextField)
@directoryController.directory = @directory
@mock_panel.stub!(:directory).and_return("Directory")
@directory.should_receive(:stringValue=).with("Directory")
@directoryController.open_panel_did_end(@mock_panel, 0, nil)
end
This is a kind of big test. What I’m doing is setting up the controller with the directory outlet, and making sure it gets set with the directory that panel will have set to it when this method is called. You notice that open_panel_did_end takes three parameters. This is a rule of Cocoa, but I don’t care about the second and third parameters, so we just pass 0 and nil.
Let’s make this guy pass:
def open_panel_did_end(panel, return_code, context=nil)
@directory.stringValue = panel.directory
end
You can see why I was reluctant to write more than one test. The method is done. Finally let’s build and run our app. It … doesn’t work. Aw heck we haven’t connected our outlets. We haven’t even created an object. This is where InterfaceBuilder starts to shine. In the library get an Object and drag it over to the Application window.

Open its Inspector and go to the information tab. That’s the one with with places for the Class, Actions and Outlets. It has a drop-down menu next to class - use it to select ChooseDirectory. Notice how we didn’t have to drag-and-drop the file into the app? Look at the Actions and Outlets, they just filled right in!

That’s fantastic. Now we can just draw our connections and build the app. Just do it already and run it. If you’ve done all the steps, and I haven’t messed this up, you should have an application that selects a directory and displays it in a text box. It’s not very exciting, but you now know two different ways to translate Objective-C’s methods into Ruby methods. Soon you will take over the world!
- Sometimes it takes a while for me to write a blog post.
- Doug would not find this polite. Jim would claim I’m being too nice.
- Real footnote this time - there is a gem called Rucola that can apparently free you from XCode. I haven’t had much luck getting it’s dependencies installed and can’t vouch for it.
- There’s that name again. I promise Eloy I’ll get it working one of these days.
- After beginning this blog post I discovered this method is deprecated. That said I strongly prefer it to the long method name, so I decided to leave it, and will do a little research as to the “why” it’s been deprecated. In the meantime you can use either, or objc_send. That third way is another blog post.
No Tag Backs
by: eric | July 3rd, 2008 | -2 comments »
Well Micah tagged me, and if I look at these XML request/responses for another hour without a break I’m going to pass out into my keyboard. Here goes.
How old were you when you started programming.
I had a Texas Instruments computer thingy that I got for my 6th or 7th birthday, somewhere in there. It played these educational games, but I noticed one day that if I didn’t put a cartridge in it a blue screen came up with a cursor. It had an instruction book and I would basically type in the programs verbatim, then do little things with it like change a color or a line. Later I had an Atari XE and it did the same thing, so I made the same little guessing game in it just like the one I made on the TI. Realistically I didn’t write anything of use until high school though.
Interestingly, perhaps only to me, my version of Hello World for the iPhone SDK was a guessing game.
How did you get started programming.
I guess that was the real answer. I played with my dad’s computers all the time but didn’t consider it as a career until I was about 16 or 17, when I realized I could probably get paid for it. Up until then I wanted to be a sports journalist. So I went to school so I could found my own game company.
What was the first real program you wrote?
What counts as “real”? The guessing game? Making horizontal lines appear on the screen? I wrote a bunch in Basic and Pascal for homework assignments, and like Micah had one of those TI calculators. The first specific one I can recall was a text-based adventure game I made for a homework assignment my freshman year. It was based on the Haymarket Bombing
What languages have you used since you started programming?
Pascal, C, C++, C#, COBOL, Assembly, Perl (but I won’t admit it), Java, Objective-C, Ruby, Javascript, Lisp, VB, Erlang, and I just wrote Hello World in Smalltalk (Squeak).
I too doubt I could write Hello World in most of those languages, and wouldn’t put them all on my resume. It’s funny because I probably would have when I came out of school, since I didn’t know the difference between “familiar with” and “able to write some code with”.
What was your first professional programming gig?
I started a web design company in college, which employed me and myself. I had two clients, one of whom paid me in Kung Fu lessons.
If there is one thing you learned along the way that you would tell new developers, what would it be?
Find great people to work with. If you’re the smartest person in the room, you need a new room, because if you’re not growing you’re dying. This is tricky when you’re new, since you don’t know a great developer from a tree stump, but take a look at Micah’s tag list. It looks like the list of authors in my library.
I would also tell them they should come to work for me as my apprentice, unless they weren’t any good. Then they can work for Jim.
What’s the most fun you’ve ever had programming?
Working with the team I work with now is fantastic. I also had a great time working Agile 2007 as part of RailsFest, and I’m looking forward to doing the same thing on the Live Aid stage this year.
Up Next
Sadly I don’t know many developer’s who keep blogs, so I’ll just echo Micah’s list and tell Paul, Jim, Doug and Matt they’re next.
#





