Home

Thu, May. 29th, 2008, 03:48 am
JBehave 2 is up on its usual svn

svn co http://svn.codehaus.org/jbehave/trunk

No ‘official releases’ yet, but if you want to play, go ahead. Examples of examples are checked into trunk.

Features include:

  • plain text scenarios
  • steps defined using annotations that match the scenarios
  • built on JUnit
  • Ensure (which is just an extension of Assert, so you don’t have to use it)
  • auto-conversion of string arguments to numbers
  • pending steps generated for anything which hasn’t been defined yet (these don’t break the build)
  • errors from scenarios are rethrown after the full scenario has been described

Our goal with JBehave 2 was to make a framework that was lightweight, easy to use and didn’t take as long to set up as JBehave 1. To that end, we’ve been driving this entirely from example code - no guessing, unless it’s obvious - and we’ve ended up with something that works quite a lot like RSpec’s story runner, but for Java.

  • To use it, simply name your scenario file with underscores, eg: i_can_toggle_a_cell and define steps in it thus:
    Given a 5 by 5 game
    When I toggle the cell at (2, 3)
    Then the grid should look like
    .....
    .....
    .....
    ..X..
    .....
    When I toggle the cell at (2, 4)
    Then the grid should look like
    .....
    .....
    .....
    ..X..
    ..X..
    When I toggle the cell at (2, 3)
    Then the grid should look like
    .....
    .....
    .....
    .....
    ..X..
  • Then extend the Scenario class with a similarly named Java class:
    ICanToggleACell.java
  • Extend the Steps class - this is where your steps will be defined, and you can have as many as you want
  • Inject these into the Scenario:
    public class ICanToggleACell extends Scenario {
    
    	public ICanToggleACell() {
    		super(new GridSteps()); // varargs, can have lots of steps
    	}
    }
  • Annotate methods in your step class to match the ones in your plain text scenario.
    public class GridSteps extends Steps {
    
    	private Game game;
    	private StringRenderer renderer;
    
    	@Given("a $width by $height game")
    	public void theGameIsRunning(int width, int height) {
    		game = new Game(width, height);
    		renderer = new StringRenderer();
    		game.setObserver(renderer);
    	}
    
    	@When("I toggle the cell at ($column, $row)")
    	public void iToggleTheCellAt(int column, int row) {
    		game.toggleCellAt(column, row);
    	}
    
    	@Then("the grid should look like $grid")
    	public void theGridShouldLookLike(String grid) {
    		ensureThat(renderer.asString(), equalTo(grid));
    	}
    
    }
  • Run your new scenario!

Future features we’re thinking of:

  • having more than one scenario in a file
  • tagging scenarios
  • better tolerance of whitespace
  • an option for pending steps to break the build
  • decent documentation to show you how you can customise filename parsing, argument parsing, etc.
  • anything you persuade us you need.

Give it a go and tell us what you think! Release 2.0 can’t be far away…

Wed, May. 14th, 2008, 01:06 pm
RIP As a... I want... So that...

If you're more interested in the results than the conversation, skip to the summary.

Recently, I've realised that a lot of BDD has been very dev-focused. There's a reason for that. Dan's a dev, I'm a dev and most of the people who helped to evolve BDD are devs.

BDD's about the interaction between the business and the technical people in software. I want to know how it's working from the other side. So, I've been learning more about the customers, and particularly, more about BAs and their role. I had the recent fortune to run into Angela Martin at Agile India, where she taught me the art of grouping stories into coherent releases, while still keeping the stories granular enough that progress can be measured and delivery made regular and predictable.

Last night at XtC I met up with Chris Matts (of Real Options fame) who told me we're doing it all wrong. "It's not an art, it's a process," he said. "You're focused on the stories; that's why you think it's an art form. The focus should be the value you're releasing."

"Right", I say. "So, when we originally planned the stories that would deliver the value, we knew what would contribute to that value. But we've lost sight of that. Changes have been made. As devs, all we have are those narratives - the 'As a <role>, I want <a feature>, so that <some benefit is achieved>'. So we need to work out which of the benefits add up to the value we're aiming for. That helps us work out which stories we should try to complete for a release. The QAs are helping us work out what's ready; the BAs are helping us work out what's important."

"That's the problem," says Chris. "You're putting the role first. It's the value that's most important. Try this: In order to <deliver some value>, as a <role>, I want <some feature>. Instead of working out why people want a feature, and whether it contributes to the value, now we're working out who needs a feature, then assigning the story. So our stories are much more focused. If all the stories that contribute to a value are ready, we release."

I guess if we get to the point where we can release with only some of the stories ready, we didn't break down our values into granular enough elements. And when we want to work out what goes in a release, it's easy. The word 'release' is more meaningful. There's some untapped money out there - some market share, some cost saving, some battle against a competitor. All the features we produce go towards releasing that value for our customers to use - and it's the value we're releasing, not the features.

Thanks, Chris, for that.

I need to also thank Dave for giving me a better understanding of what a value is.

In summary: my preferred narrative now reads:

In order to <achieve some value>
As a <role>
I want <some feature>.

Because, in order for my work to have any meaning, as a dev, I want to know why you want it.

Edit: Chris said he posted this to the Kanban group on Yahoo, but they aren't responsible for it. Sorry, Chris, didn't mean to misaappropriate! See you on there soon.

Thu, Apr. 24th, 2008, 03:16 pm
Running your own Retrospective

I'm running a training course for TDD and OO design at one of our clients.

Normally when I teach this, it's to Thoughtworkers or client staff working with Thoughtworkers. This time, I'm teaching fairly experienced clients who have some idea of OO already. I've been trying to teach more advanced techniques - communication with customers and how it drives design; starting with the UI and a good concept of 'done', etc.

I could see that occasionally, some of the participants looked uncomfortable. Whenever I asked them for feedback, they told me that they were having fun and learning a lot! Yet I could see that they were still uncomfortable - they just couldn't tell me why.

So, at the end of the second day, we ran a small retrospective. Normally, I would ask a facilitator to run the retrospective for me, but we didn't have one. Here are some things I did that seemed to work, and help the retrospective to run smoothly.

Make them feel safe with you



It's awkward running a retrospective when you're the one who's likely responsible for the things that aren't working quite as well as they could. It's especially true if you're a stranger to the group, or the group isn't used to giving and receiving feedback, or both. I wanted to introduce to the participants the idea that they should feel safe giving me feedback; that I would react to that feedback positively and wouldn't criticise them for giving it. I also wanted to give them an idea of how they might run retrospectives for themselves.

So this is what I told my participants:

I've run this training course for a lot of people. I come with a very generic course, and tailor it as best I can to the people who turn up. Every group is different. Some people prefer different techniques to others. You no doubt have your own thoughts about what might work for you.

I'd like to use a retrospective format to get an idea of how best I can tailor this course for you.

In a retrospective, we start with the Prime Directive: that no matter what we find out, we know that everyone is a good person and has done the best job they can in the situation. I believe you're all good people. I hope I'm a good person. I think that the job I'm doing here is a good one, but I'd like to make it better. There are ways in which you could phrase feedback positively. That would be nice! But even if you can't find a way to express things positively - I still want the feedback. I have a lot of confidence in myself and my abilities. I can take it!


Then, I ran the safety check. The participants felt safe enough (mostly 4s on a 1-5 scale) so I went ahead.

Make them feel safe with each other



I asked all the participants to draw a picture to represent how they felt about the course so far.

I could see their eyes light up as everyone put the pictures on the board. Eight faces with question marks, puzzled expressions and light-bulbs. Everyone felt slightly puzzled, slightly confused yet enlightened! I think this helped them realise that their confusion wasn't unique.

Make them feel safe with themselves



People are usually happier giving feedback if they can find a way to phrase it positively. Fortunately, this is easy! For every "less of" there's usually a "more of"; for every "stop doing" there's often a "start doing"; for every "fear" there's a "hope".

Often in retrospectives we insist that people put one thing in each category. I didn't want to do that this time, because I felt that people would be uncomfortable with the idea of giving me lots of "less of". Instead, I left them free to think of more positive ways of expressing what they wanted.

I encouraged them to think of ways of changing things by adding three categories:

  • More of / hope

  • Less of / fear

  • Puzzles


I explained what the categories were for, and asked them to come up with about five things that they wanted to put in these categories. To show them what I meant, I drew a pint of beer and put it in the "hope" category, then told them that I hoped that we could all go out one evening for something less formal.

Then I let the participants loose on the board!

Proof that it works



The participants wrote things like "Hope for more time to come up with a solution!","Hope not to be so confused by other people's designs", "Hope for more tea breaks", "Hope for better understanding", "Hope we get to learn more about Agile", etc. There were very few fears - "Afraid I'll fall behind" - and a couple of puzzles that were either easy to answer or I promised would be answered as part of the course.

I asked them to talk in more detail and give examples of times when they'd been confused, etc. We came up with a lot of action items as a result of the things they put on the board:
  • Break down exercises into smaller chunks

  • Baseline code bases (move to one common solution for the exercise) frequently, to allow people to swap pairs and stop them being overwhelmed by the differences when they do

  • Allow more time for analysis of the solution and for questions

  • Participants to tell me when they want a tea break

  • Pub next Thursday


I also found some things which they wanted me to teach which weren't really part of the course, so I made a mental note to slip the easy things in when the time came, or provide them with links to resources where they could learn themselves.

I checked that they thought the action items would meet their hopes. That feedback was very valuable, and far more useful than "Oh, we're having fun and learning a lot!"

The safety check is the most important thing



It was very important to me that the feedback I got was honest and accurate. For that reason, I was extremely careful with the safety check. I made sure that it was visibly anonymous - I got one of the participants to gather up the pieces of paper, and made sure that they used identical paper and pens so that no one could be identified.

If they hadn't felt safe, it would have given me feedback about my approachability, and how well I had expressed my desire to get feedback. It might also have indicated that people didn't feel safe with each other. I guess if that had happened I would have run more icebreakers, more fun exercises that let people relax, and I'd have looked carefully to see if there was any personal feedback that I needed to take on board or give to individual participants. I'd also have tried hard to find an independent facilitator to run the retrospective - but I wouldn't run it with a low safety check. I also let the participants know this, and reassured them that I'd do some different things to try and make the environment better if the safety check was low.

Thanks Pat!



Pat Kua loves retrospectives, and has taught me their importance and a number of techniques for running them. They're my second-favourite practice. My favourite is Small Releases - actually delivering the things you promised to deliver - and I use retrospectives to work out why I can't deliver, or how we can deliver better, or sooner. This can apply just as well to training courses as to code.

I was quite surprised by how well the retrospective worked. Talking about it with my co-trainer Arvind afterwards helped me realise how the things I had done instinctively added to the environment of safety and helped the participants give me the feedback I needed. I hope it's helpful for you too.

Mon, Apr. 21st, 2008, 05:25 pm
Agile Mumbai slides are up

Naresh Jain has very kindly put up the slides from my BDD presentation at Agile Mumbai.

I deviated quite heavily from previous presentations I've done and talked about the history of BDD, how it evolved and the people and events that made it happen. You can find links on the last page to some of the more influential sites, groups and people - all good places / entities to hang around for innovative thought and challenging questions.

Many thanks again, and particularly to Dan for being unavailable, Naresh and Agile India for inviting me instead and Thoughtworks for letting me go.

Mon, Apr. 21st, 2008, 01:17 pm
BDD for TDDers

Anthony Bailey and I had a conversation over email about what good, experienced TDDers might get out of BDD.

If you've been wondering what all the fuss is about, maybe this will help! Thanks, Anthony, for tidying the conversation up so nicely.

Thu, Apr. 17th, 2008, 04:28 pm
JBehave 2, naming tests and developing libraries with BDD

Peter Bell and I had a great conversation over Skype yesterday, which he's kindly blogged. We covered test names, and also talked about how to develop libraries using BDD. Again, this is how I do things; it's not necessarily the only way.

Peter's mentioned JBehave 2, so the secret's out now - yes, it's in progress. It's not publically available because it's just a spike at the moment. We're starting afresh, learning some of the lessons that made JBehave 1.0 hard to use, taking advantage of JUnit 4's features, and drawing heavily on the success of RSpec.

Our goals for JBehave 2 include:
  • no internal support for mocking - should be able to use any of the libraries

  • extends JUnit - right-click and run both behaviours and scenarios

  • uses Hamcrest's matchers

  • uses plain-text scenarios à la RSpec



Here's a sneak preview of the spike so far.

We have a scenario file, i_can_toggle_a_cell:

Given a 5 by 5 game
When I toggle the cell at (2, 3)
Then the grid should look like 
.....
.....
.....
..X..
.....
When I toggle the cell at (2, 4)
Then the grid should look like 
.....
.....
.....
..X..
..X..
When I toggle the cell at (2, 3)
Then the grid should look like 
.....
.....
.....
.....
..X..


We have a small class in the same package to run this, called ICanToggleACell.java (the Scenario class is a JUnit test):

package com.lunivore.gameoflife;

import org.jbehave.scenario.Scenario;

import com.lunivore.gameoflife.steps.GridSteps;

public class ICanToggleACell extends Scenario {
	
	@SuppressWarnings("unchecked")
	public ICanToggleACell() {
		super(new GridSteps());
	}
}


And we have steps defined thus:

package com.lunivore.gameoflife.steps;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.jbehave.Ensure.ensureThat;

import org.jbehave.scenario.annotations.Given;
import org.jbehave.scenario.annotations.Then;
import org.jbehave.scenario.annotations.When;
import org.jbehave.scenario.steps.Steps;

import com.lunivore.gameoflife.domain.Game;
import com.lunivore.gameoflife.view.string.StringRenderer;

public class GridSteps extends Steps {
	
	private Game game;
	private StringRenderer renderer;

	@Given("a $width by $height game")
	public void theGameIsRunning(int width, int height) {
		game = new Game(width, height);
		renderer = new StringRenderer();
		game.setObserver(renderer);
	}
	
	@When("I toggle the cell at ($column, $row)")
	public void iToggleTheCellAt(int column, int row) {
		game.toggleCellAt(column, row);
	}
	
	@Then("the grid should look like $grid")
	public void theGridShouldLookLike(String grid) {
		ensureThat(renderer.asString(), equalTo(grid));
	}

}



I'm excited that this actually works. The next step is to get appropriate error messages when the scenario fails! We're working hard to get this out to you as soon as we can; watch this space.

Tue, Apr. 1st, 2008, 03:25 pm
Your horoscope for April

How people



You've spent years making yourself invaluable to your friends, family and colleagues. Your confidence is at an all-time high - how many people in the world can do what you do? Watch out, though; pride cometh before a fall. You're a deep roller. Let's hope one of your parents was not.

Your tool of the month is Mingle Proj-o-matic.

Why people



Yesterday the room was crowded. The smell of pressure hung heavy in the air. The quiet tap of fingers on keyboards, the whispered conversations, the passionate arguments, the occasional round of applause as a story reaches completion - these were the sounds that punctuated your life. So how come it's suddenly so quiet?

Your word of the month is anachronism.

Who people



They promised a future in which robots clean the house, food is manufactured by holes in the wall, money is irrelevant, war is history and learning is taken in pill form. It hasn't happened yet. There'll always be work for people people - shelve any plans you had for holiday this month; you're needed right where you are!

Your pub of the month is Leela Palace, Bangalore.

When people



A blank page can stifle the most imaginative mind - sometimes creativity requires a place to start. Still, if mistakes are cheap then there's room to play. Imagine a world in which you could write things down in English, and just have it work. Imagine what would happen if you didn't even need to write it down. The brain is the most amazing computer in the world... so far.

Your quote of the month is:
Any sufficiently advanced technology is indistinguishable from magic.

--
What's my sign?

Mon, Mar. 31st, 2008, 04:40 pm
Perverse Incentives

I proposed an Open Space session at Agile Mumbai to discuss Perverse Incentives and gaming the system in Agile projects.

A perverse incentive is one which produces an effect that works against the interests of the people who proposed the incentive in the first place. Gaming the system can be thought of as working deliberately through the path of least resistance or greatest reward, towards the incentive, even if the effect of working that way is perverse.

Many thanks to the Open Spacers who came up with the practices.

Here are some situations which led to the discussion.



  • Situation 1: An IM notices that the team often underestimate cards. He berates the team for not spotting the problems that will slow them down and fixing them or at least factoring them in.

  • Desired effect: The team deal with the problems that are slowing them down and speed up. The estimates become more accurate once the surprises have gone away.

  • Actual effect: The team factor in larger estimates and contingency - it's easier than spotting and dealing with the tricky problems. Because they don't always need that contingency, there's less pressure to finish the tasks to which they've committed themselves. Without that pressure, they slow down.


  • Situation 2: Two developers go off on their own to investigate a possible solution to a tricky problem. They don't tell anyone they're doing it. The solution they're thinking of was already investigated and discounted. When the PM realises how much time has been wasted, he puts a process in place to ensure that any work that gets started has been approved with the team lead, that the business value has been agreed with the BAs, and that acceptance criteria have been defined. Anyone who starts work without following the process is reminded of the time wasted on the project by people doing work that's not valuable.

  • Desired effect: Less time is wasted doing work that doesn't deliver business value.

  • Actual effect: Developers waste time waiting for the team leads and BAs to come out of meetings. Refactoring and other cleaning up, which doesn't deliver business value directly, slides. The project slows down. Developers feel untrusted, and project leads spend all their time chasing up developers to make sure they're following the process.


  • Situation 3: The customer is unavailable when the developers want him. The developers spot the bottleneck and ask the business to assign more of the customer's time to them.

  • Desired effect: The customer answers the developers' questions, and the developers can deliver the right thing.

  • Actual effect: The customer loses touch with the users and with his peers. He doesn't get to use the end product, so becomes less interested in it. When the product is delivered, the users want many changes and the application no longer solves the needs of the business. The business also suffers because the customer is an skilled expert, and is less available to help the business in its day-to-day work.


These were all real situations which we either encountered or were concerned about happening on our projects. We also brought up some examples outside of the software domain, in the fields of healthcare and education. That prompted a slew of other examples, and the discussion kicked off.

These are the questions we wanted to answer:



  • What stops processes delivering their desired effect? When processes are created that do deliver the right effect, how are they crafted and what is their focus?

  • What meta-practices could we put in place that would help stop perverse incentives from being created?


Human perception skews us towards perverse incentives.



During the discussion, we quickly realised that we have an emotional attachment to weakness. Good practices and implemented solutions are invisible; they don't impinge on our consciousness. A bad practice or a problem stops us from doing what we want. It demands our attention; demands that we stop what we're doing and fix the problem. So our focus is skewed, and we automatically allow our efforts to drift. We fix the bad practices, instead of introducing good practices. We confront the problems, instead of finding a route around them.

Some practices which help us avoid perverse incentives.



NB: Whenever I've used words like "measure", I would also like to include curious observation, intelligent reasoning, judgement through experience and blind intuition - anything which is going to affect the changes you make as a result of the measurement. Some of these ways of measuring are more practical than others, depending on the context, and who's doing it. Pick one that works for you.

  1. Measure reality, not comparative reality.

    Don't measure how many stories were underestimated; measure how much they were underestimated by. Don't measure how often the customer is unavailable; measure how many hours he's there / not there. This will help you to measure the true scope of the problem. It will also help to remind you to...


  2. Keep the balance when measuring.

    If you're measuring underestimation, also measure overestimation. If you're measuring how often a customer is unavailable when you want him, also measure how often a customer is available, but unused. If you're measuring how many developers waste time because they haven't followed the process, measure how much work gets done because developers don't have to wait to follow the process.


  3. Consider aspects of the practice you're about to change that might be beneficial.

    Consider how those meetings in which the customer spends his time might help your project. Measure how much the developers who went off on their own learnt about the domain and the technology, and how much work they got done in the following month as a result. Consider the time that project leads who aren't chasing up errant developers can spend on other things.


  4. Measure objectives as directly as you can.

    If you want to make your customer happy, get your customer's feedback, not the devs'. If you want to deliver business value faster, measure how much business value you're delivering. If you think that rogue developers are slowing down development, look at the change in velocity. Don't guess or apply reasoning if you can get real figures.


  5. Fit your process to reality, not reality to your process.

    If your process requires your customer to be there and he's not, maybe change the process - get some BAs, or arrange for another customer to help you. If the estimates are consistently awry, change the process of estimation rather than trying to fix problems that may be unfixable (there is no silver bullet). If your developers waste time doing something that's already been investigated, make sure the results of investigations are published in a place where they'll read it.


  6. Concentrate on the things that enable you to get work done.

    Counteract the skew towards weaknesses by deliberately emphasising strengths. We know this works when applied to people and their abilities. It can also work when applied to a process and its practices. Appreciative Enquiry can help create an environment conducive to spontaneity, to getting things done and coming up with imaginative solutions based on things that worked before (and which are therefore less likely to be perverse).


  7. Give feedback, especially if something or someone works well.

    We tend to focus on weaknesses in ourselves. Help the team appreciate their strengths, and avoid focusing on their weaknesses. If there's something that needs doing and nobody is doing it, don't berate the team - find someone who does it well and get them to join in.

  8. Provide evidence when providing feedback.

    What evidence is there that the developers have slowed the team down? That the customer's unavailability has negatively affected the project? How many unfinished or rejected stories were there as a result?

    What did the developers learn as a result of their investigation? What did we learn about our processes? What did the customer provide us with as a result of the meetings?


  9. Make sure that the person in charge of an aspect of the project has an interest in maximising that aspect.

    Don't praise the IM because his team meets the estimates - praise him because the amount they're actually doing goes up.

    Make sure the customer assigned to answer the team's queries has an interest in the final product.

    If you want developers to stop wasting time, introduce them to the customer, and ask the customer to tell them how valuable their work on the end product is - give them the motivation to deliver.


  10. Bring in a fresh perspective.

    Good improvements are often incremental. Sometimes it's hard to see which practices you've put in place that enable a project everyone said couldn't be done. An external observer can make you re-examine what you do, as well as helping you to pass on those unique practices to other projects and teams.

    Alternatively, try teaching your practices to people who aren't familiar with your project or methodology. When they ask questions about how that works, given your situation, write the answers down.

Wed, Mar. 26th, 2008, 08:36 pm
Ignorance is bliss

I used to get angry with ignorant people, until I realised that it only made them hide their ignorance. Then I realised that I was ignorant too. Now I love ignorant people best of all. I deliberately seek them out; they give me the greatest buzz in the world.

I particularly love helping them appreciate their ignorance, mitigate against it, and eventually displace their ignorance to somewhere else.

Some people like to call this movement "learning" and the act of helping people with it "teaching", but really, the idea that we can somehow put an end to ignorance is entirely illusory. The only thing we can do is to move the ignorance around, and find out which places it moves fastest and with the most fun attached.

We call those places "strengths", and people who can move their ignorance quickly are "fast learners". "Experts" have done more shifting of their ignorance than others. "Gurus" are the ones who've managed to handle an exponentially increasing amount of ignorance, finding more of it in themselves than most people can ever handle. Some of them have found patterns for shifting the ignorance quickly. It's still there, though.

I want to be a guru one day. Gurus are the best. They teach me all the new places of ignorance that I never knew were there, and open my mind up to just how much of the stuff there is. I can't imagine anything worse than running out of things to learn. Having lots of ignorance to play with is just lovely.

Now, where did I put that Ruby tutorial?

Wed, Mar. 5th, 2008, 05:15 pm
Do I always write a test?

I've just been reading the debate between Bob Martin and Jim Coplien on InfoQ, centred around Bob's assertion that "nowadays it is irresponsible for a developer to ship a line of code he has not executed in a unit test."

I have to confess... despite my desire for BDD, I don't always do automated tests for everything. The place I'm most likely to skip automated tests is when something shows up in a GUI.

That might strike you as odd, if you know that BDD's outside-in starts from the GUI and works downwards. It's probably less odd if you also know that automated testing is no substitute for manual testing. Here are a couple of things for which I haven't written a test.

From Hellbound, the Tetris game in JBehave's examples:

public class AcceleratingHeartbeatBehaviour extends UsingMiniMock {{

    public void shouldBeatAfterElapsedTime() throws Exception {
        <Test code exists>
    }
    
    public void shouldBeatMoreQuicklyWithEachBeat() {
        // No way of ensuring this with automation. 
    }
    
    public void shouldStopAnyExistingTimerThreadsBeforeStarting() {
        // No way of ensuring this with automation. 
    }
    
    public void shouldMoveImmediatelyToNextWaitingPhaseWhenSkippingABeat() {
        // Nor this.
    }
    
    public void shouldNotBeatAfterBeingStopped() throws Exception {
        <There's some test code for this one too>    
    }
}


It's not entirely true that there's no way of ensuring these things with automation (and the main drawback here was the time it took, which spoils the < 5 second regression test suite). One could extract out clock classes, etc. But then, you're sacrificing readability and ease of design - a single class is enough. Why would you do this, anyway? The only way of telling whether the timing of a game is fast enough to be challenging but slow enough to be feasible is to play it!

It's much the same with this, from the same Game of Life and GameFrame class as the last post:

public class GameFrameBehaviour extends Behaviour {

    @Test
    public void shouldHaveAButtonForTheNextGeneration() throws Exception {
        <See last post for this code>
    }
    
    @Test
    public void shouldCreateCellsInGameCorrespondingToMouseClicks() {
        // I'm not putting any examples here, because in reality the
        // only way to tell if this works is to test it manually!
    }

}


I tried writing an automated test to check that mouse-clicks corresponded to cells appearing in the grid. I got it wrong; the automated test passed but the cells were appearing in the wrong place. I made the same mistakes with Swing's coordinate system in both the test and the code. This time round I can't even be bothered; it's easier just to use it, check that I got it right, and never change the behaviour of the grid GUI again (at least, not without manual retesting).

There are other places where I'll skip unit tests too - getters, mostly. I'll even skip automated system-level tests if there isn't an appropriate harness. I've done this in my own code; I've done this at client sites.

Do I feel guilty or unprofessional?

No.

Does it stop me describing how the class behaves?

No. I usually add empty methods to describe an aspect of behaviour that I don't want to test. At least they get read; they also remind me that I have a missing test, and should use careful inspection if I change the code.

Does it mean that I can get away without testing it altogether?

No. I have to test it manually, from the GUI, instead.

But then, you're doing that anyway... aren't you? Because I think Bob would agree on one point with me: nowadays it is irresponsible for a developer to ship a line of code he has not tested, and all your tests are worthless if it doesn't actually work.

Wed, Mar. 5th, 2008, 02:40 pm
Four mocks? One test? No problem!

Last year, my colleague Ben introduced us to the joys of hand-rolling mocks. This allowed us to ignore interactions we weren't worried about, leading to cleaner tests.

This year, I'm mocking again. I've mentioned it briefly before, but now that I've used Mockito a bit more, I really love it. Here's a quick summary to show why.

public class GameBehaviour {
    
    @Test
    public void shouldApplyRulesToOriginalGridThenEachGeneratedGridInTurn() {
        // Given
        Rules rules = mock(Rules.class);
        Grid firstGrid = mock(Grid.class);
        Grid secondGrid = mock(Grid.class);
        Grid anyGrid = Grid.NULL;
        
        GridFactory factory = mock(GridFactory.class);
        stub(factory.createGrid(anyInt(), anyInt())).toReturn(firstGrid);
        
        stub(rules.applyTo(firstGrid)).toReturn(secondGrid);
        stub(rules.applyTo(secondGrid)).toReturn(anyGrid);
                
        // When
        Game game = new Game(5, 5, rules, factory);
        game.nextGeneration();
        game.nextGeneration();
        
        // Then
        verify(rules).applyTo(firstGrid);
        verify(rules).applyTo(secondGrid);
    }
}


There are some quite complex factors in this Game of Life - infinite, bounded or wrapped grids, rules which could be Conway's or the High Life rules, etc. - hence the design pattern overkill. Here's something simpler:

public class GameFrameBehaviour {

    @Test
    public void shouldHaveAButtonForTheNextGeneration() throws Exception {
        // Given
        WindowControl windowWrapper = new WindowControl("game.frame");
        Game game = mock(Game.class);
        new GameFrame(game);
        
        // When
        windowWrapper.clickButton("next.step");
        
        // Then
        verify(game).nextGeneration();
    }
}


I leave it to you to work out what these look like with other mocking frameworks. You can look at Szczepan's comparisons to get an idea.

Thanks, Szczepan.

Mon, Mar. 3rd, 2008, 02:28 pm
Your horoscope for March

How people



God grant you the serenity to accept the things you cannot change, the courage to change the things you can and the fortune to have little need for either. Some things exist just to make your life easier. Hope you get yours soon.

Your tool of the month is the MacBook Pro.

Why people



It seemed a simple enough task, so you gave it to someone else to do! You thought that a few hints and tips would be enough to set them in the right direction - but now you come to look at it, you realise that hidden underneath the simplicity was a right can of worms, which they've happily opened up and tipped back onto your desk. Messy.

Your word of the month is lumbricide.

Who people



We started with drums and beacon fires, moved on to mail and semaphore and eventually developed the radio. Now the internet provides the ultimate in communication. Pity the signal-to-noise ratio is so low! Still, with sites like FaceBook and MySpace, you too can ensure that the web is a better place for having you in it. If you get the chance, send me zombie blood.

Your pub of the month is Styx, Bangalore.

When people



You know you're too busy when you get off the plane and get onto the phone; get off of the phone and get on with the job; get off to a good start and get on with the new guy. With all this getting on and getting off, it's hardly surprising you've forgotten something. If only you could remember what it was!

Your quote of the month is:

Footfalls echo in the memory
Down the passage which we did not take
Towards the door we never opened


T.S. Eliot

--
What's my sign?

Mon, Feb. 18th, 2008, 03:14 pm
BDD on Wikipedia

I finally got around to updating / rewriting the BDD page on Wikipedia.

This is either based on things Dan's said or written, or things others (including me) have said or written and which he's approved in my hearing as "official BDD". I may well have made mistakes. I haven't written any in-text citations as yet; will do that as and when I next have time (if no one else gets there first!)

Now, when someone asks me what the difference is between BDD and TDD, I have somewhere to point to. Many thanks to the contributors who wrote the predecessor. BDD's come a long way since the article was first written, but your thoughts really helped me formulate mine.

Go edit. :)

Fri, Feb. 8th, 2008, 07:37 pm
Introducing Tyburn

When I first started working with JBehave, I wrote a Tetris game. I had trouble finding Swing harnesses that didn't depend on JUnit. So I wrote one.

JBehave 2.0 won't include Swing support. The harness was completely independent of JBehave anyway. So, we decided that I should pull it out into its own project.

At the moment, it works by finding a named window and components. Here's an example of how to use it:

WindowControl control = new WindowControl("my.named.frame");
control.clickButton("a.button");
control.enterText("a.textfield", "Text1");


I've tried to make it fast, minimal and extensible, since everyone seems to want different things from their Swing harness. If you have a request for a feature, please let me know!

A shout goes out to Szczepan for the gorgeous Mockito, which I used in the tests examples. Finally, mocks that can do Given / When / Then, instead of Given / Expect / Finish recording / When / Then go back to expectations cos you've forgotten what you wanted your code to do in the first place.

See lots of examples, together with Mockito beauty, here.

Fri, Feb. 1st, 2008, 09:24 am
Your Horoscope for February*

How people



Sometimes it's nice to get your head down without any distractions, but beware - are you cut off from the rest of the world? No one is stopping to wait for you. Get the most important things done now, and leave yourself plenty of time to play. Other gems are buried in the sandpit.

Your tool of the month is Quicksilver.

Why people



It's always strange when an alien to your planet turns out not only to speak your language, but to read your mind. Still, they're here for a reason. From higher up, they can see everything you can and more - is there something beyond your horizon that you need to know about?

Your word of the month is Maelstrom.

Who people



Remember all those people you haven't seen for a while? It's time to look them up and drag them out of hibernation. You may find it difficult to get in touch, but persevere - perhaps they're looking for you, too. When the storm hits, the best place to be is in the centre of everything.

Your eatery of the month is Barbeque Nation, Bangalore.

When people



The tree you've been tending for the past few years has finally borne fruit. Ironically this means it's time to leave your garden behind, but don't worry; others will learn how to tend it. Pack a few seeds, your favourite books and just go - the people you rely on won't be far behind.

Your quote of the month is: Hearts that are delicate and kind and tongues that are neither - these make the finest company in the world..

--
*I stopped doing these because I didn't think so many people were interested. Turns out I have some fans in India, and some comments I hadn't read. Thank you! The Horoscope returns!

What's my sign?

Mon, Jan. 28th, 2008, 05:06 pm
Given, When, Then - the only way?

Someone told me that out there, somewhere, are people who believe that "Given, When, Then" is the only way to analyse a story. I don't believe it's true. Sometimes there are more concise ways to get the same information. For example:

"Refunded or replaced items should always be returned to stock, unless they're faulty."

That's four separate scenarios, encapsulated quite well in a very short sentence!

So why do we emphasise Given, When and Then in BDD?

Well, we can describe the behaviour in a different way. However, when we'd like to know when we're done, we have to use a concrete example, whether it's automated or manually driven. The only way to know whether the above sentence holds true for our system - whether the behaviour is correct - is to actually run through all four scenarios. Until they all work, we're not done.

So, perhaps you, the business representative or analyst, don't like using the language of contexts, events and outcomes. However, we devs use it all the time, as do QAs. However you get the information, and however you phrase it to us, the examples that you pass on to us define the scope of the story, the detail, and the end product.

An automated example sets up some contexts, causes some events to occur, and checks for certain outcomes (and perhaps then uses the result as the basis for more events and outcomes).

A manual test does this too.

With automation, particularly, it seems that contexts, events and outcomes are frequently reused to create different scenarios. Phrasing things in a way which makes them explicit can sometimes help us to reuse code in our scenarios, making the regression test suite cleaner and easier to maintain. This makes it easy to create new examples for behaviour we haven't coded yet, which means we know more quickly when we're done, which means you get your system delivered faster.

If we get the wrong Givens, Whens, or Thens, or we've missed a couple of contexts that might lead to different outcomes, then perhaps the system we produce might behave in ways that you didn't intend, if at all.

You don't have to be pedantic about the language - it's OK to balance common sense with detailed explanations, and concentrate on the unexpected and on edge-cases - but if in doubt, you may find that using examples makes things a little clearer.

You may also want to read through our examples when we're done. Just to check.

Thu, Jan. 17th, 2008, 09:59 am
Find your own way to cook

A mother was cooking a joint of meat for her family. She cut off a large slice from the side of the joint, then put both pieces into the gravy.

"Why are you doing that?" her daughter asked.

"It helps it cook properly. That's the way my mother always did it," the mother replied.

"Why does it help?"

"I don't know. Maybe I'll ask your grandmother next time I phone her."

So the mother phoned the grandmother. "Why do you always cut a slice of meat from the side when you cook the joint?" she asked.

"It helps it cook properly," said the grandmother.

"But why?"

"I don't know. It's just the way my mother taught me to do it. Maybe we should ask her why!"

So the family went to see the elderly great-grandmother. "Why do we always cut a piece of meat from the side of the joint, before we put it in the sauce?" the mother asked.

"You still do that?" the old lady laughed. "I love you, and love that you trust in what I do, but you should find your own way to cook. I did it because it was the only way it would fit in my pot!"

(My father told me this story when I was a child; apparently it appears in "Surely you're joking, Mr Feynman" by Richard Feynman.)

Thu, Dec. 13th, 2007, 12:54 pm
10 signs of work goodness - revisited

You know work is good when:
  1. Your smile is infectious, even on the tube.

  2. Every day you find out something new...

  3. ...and pass on something to someone else.

  4. You wonder how you're going to have fun, not when.

  5. No tunnel is so long that you can't see the light at the end...

  6. ...and you're learning to climb hills instead of ploughing through them.

  7. The team can reach agreement on anything except where to have lunch.

  8. You come to work with questions, and leave with different questions.

  9. Your friend asks you, "How was your day?" and really wants to know.

  10. Sometimes you amaze yourself.


I wrote these ten things down back in January last year. The client I was at was difficult, and I wasn't actually getting any of these things. It seemed like a positive way to express my frustration.

A scant eight minutes after I wrote the post, I got a phone call telling me to pack my bags. I was going to Xian. I left the difficult client behind.

Now, looking back at those ten things, it seems to me that despite the occasional off day, I have them. All of them. Better still, I've learnt how to keep them, even at difficult clients.

That's why I'm revisiting this post. It's also why, after three years at the job, I'm still proud to be a Thoughtworker. You guys rock my world.

Fri, Nov. 30th, 2007, 03:38 pm
A Mind of Its Own

I'm reading the book "A Mind of Its Own", by Cordelia Fine. I sometimes find it hard to make headway with this kind of material and put it down after the first couple of chapters, but for whatever reason this one has gripped me.

It's all about the strange tricks that the brain can play on itself, and the things that people do as a result. Particularly, we become blindsided to our own faults.

Then I came across this perfect example, in an article about Donald Trump's plan to build a £1 million golf course being turned down by Aberdeen council, with the help of assorted committees, protesters and a fisherman:

Sorial defended accusations the Trump team had been "arrogant and patronising" in its approach. "There's a view we are arrogant. We are not arrogant. We set certain standards. It may be incomprehensible to smaller minds, but we have always set high standards. We presented them with a plan and hoped they could open their minds, but it was too much for them."


I can't understand how anyone could misconstrue such grace and humility. Shocking. Chalk one up for the Aberdonians.

Mon, Nov. 19th, 2007, 02:40 pm
Bug Driven Development: a danger of delivering the pretty GUIs first

After my last post, Negin and I were quite pleased that we'd got as far as we had.

So was our Business Analyst. "So, this story that was estimated at 3 days," she said. "Can I say it's only taken one?"

"No! We're not done yet!" I protested.

"Really? It looked like you were almost done on Friday... what happened?"

Oh, well. At least we know it looks good.

20 most recent