A couple of days ago I watched the fantastic “TDD as if you really meant it” session by Keith Braithwaite on Infoq. I highly recommend it even if you are not a developer ( writer of code ).
I love the simplicity of the process that Keith tells the session attendees to adopt. It is a great exercise in emergent design that highlights how easily developers make assumption about the design rather than let it emerge.
The only thing I questioned was Keith’s suggestion that the developers start “anywhere”. As Keith said this my immediate response was “Start with the ouputs”. I commented on the InfoQ article as such.
I got the impression that a number of the people in the session started with the inputs. They soon ran into problems and started making assumptions about the design. This is exactly the opposite of the Feature Injection process which starts with the outputs. A colleague ( developer ) and I started going through the Tic-Tac-Toe exercise using pseudo-code. (I’m hoping to complete the exercise using C#).
As we worked through the exercise starting from the outcome ( Game Over ) and working into the functions ( isWon, isStaleMate ) generating Mocks as we went along, we suffered from none of the problems that the people in the session encountered. We had none of the desire to make assumptions about the design. More importantly, we quickly encountered the fundamental domain questions about Tic-Tac-Toe ( 3×3 Grid? 4×4 grid? 3 dimensional grid? ). How do we test to make sure the isWon works properly. Issues about inputs were not even discussed. Issues about display were not discussed. We had lots of options. We drove right into the riskiest part of the development from a domain perspective.
Previously I have never commented on TDD but it seems to me that TDD should also start with the outputs and work to the inputs. In effect, Feature Injection, should be injected into TDD.
I’m waiting for the flames!
Disclaimer – I assume someone else has already said this but I just am not aware of it.
I will post the code when I do it in C#
Pseudo Code: Code in red
Test 1 – isFinished is TRUE
iSFinished() return True
Test 2 – isFinished returns FALSE
isFinished() return game.Finished()
Create mock game.isFinished returns False
Test 1 Fails. Refactor test 1 to use Mock game.isFinished returns True
Test 3 – game.isFinished is TRUE
game.isFinished() return TRUE
Test 4 – game.isFinished is FALSE ( GIVEN NOT isStaleMate AND NOT isWon WHEN game.IsFinished THEN FALSE )
gameisFinished()
if game.isWon() || game.staleMate() then
return TRUE
else
return FALSE
2 Mocks game.isWon() returns FALSE and game.isStaleMate() returns FALSE
Test 5 – game.isFinished is TRUE, isStaleMate ( GIVEN isStaleMate WHEN game.IsFinished THEN TRUE )
2 Mocks game.isWon() returns FALSE and game.isStaleMate() returns TRUE
Test 6 – game.isFinished is TRUE, isWon ( GIVEN isWon WHEN game.IsFinished THEN TRUE )
2 Mocks game.isWon() returns TRUE and game.isStaleMate() returns FALSE
Test 7 – Test 7 – game isFinished is TRUE, isWon and isStaleMate ( GIVEN isWon and isStalemate WHEN game.IsFinished THEN throw exception )
2 Mocks game.isWon() returns TRUE and game.isStaleMate() returns TRUE
gameisFinished()
if game.isWon() || game.staleMate() then
return TRUE
elseif NOT(game.isWon() )&&NOT(game.staleMate()) then
return FALSE
else
raise exception (“Its broken because it should be possible to win and be in stalemate”)
The coding finishes when all the mocks are all implemented.
Coding to be continued…
Note that the GIVEN WHEN THEN calls out the Mocks to use. Mocks were the inspiration for the pattern.
Notes:
Tic Tac Toe ( Winning ) | ||||||||
1 | 1 | 1 | 1 | |||||
2 | 1 | 1 | 1 | |||||
3 | 1 | 1 | ||||||
4 | 1 | 1 | ||||||
5 | 1 | 1 | 1 | 1 | ||||
6 | 1 | 1 | ||||||
7 | 1 | 1 | ||||||
8 | 1 | 1 | 1 | |||||
9 | 1 | 1 | 1 |
Display
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
January 20th, 2012 at 1:43 pm
starting with the output also has a nice echo of pull rather than push (in the kanban sense – although as we both know, kanban sucks 😉
January 20th, 2012 at 1:46 pm
First time people try this technique they start focusing on the simplest thing which is the input. After a while you’ll see that people start realizing that they should really focus on the pure behavior of the system. In most cases this means that people need to start thinking outside in instead of inside out.
I’ve seen the same struggle when people try to write Conway’s game of life and starting from the inside out. The whole idea of this technique is that you don’t assume anything upfront. So there is no inside out option. That’s why I always suggest people to start from the rules of the game, what happens when a generation moves to a new stage.
I like your post and I’m curious about your implementation in C#. If I can just give you one piece of advice on how you can make this even better. Try to write your tests in a more natural naming. If your tests are more descriptive, your implementation will probably be more descriptive as well and you end up with a better naming all over the system.
January 20th, 2012 at 1:53 pm
Hi Chris,
I remember Kent Beck’s book “TDD by Example”.
One of the best advices I remembered is that when writing a test, it’s better to start writing the assertions before anything else.
What I felt when I read this is that the concept about starting with output is deep into TDD mindset
January 20th, 2012 at 2:27 pm
Recently I built a feature from the ‘outside’ to the ‘inside’. And it brought a much simpler design with it.
One thing you have to keep in mind though, in this case you have a few mocks and you implement them later. But, in a ‘realworld’ solution you can have multiple mocked objects. You need to be aware that when you start implementing one of them you might also introduce new mock objects.
All in all, keep a track of the mocked objects as you go. You might forget some.
Funny thing is, if you actually return stubbed data, you can actually see it working in your application. The more you implement the mocks(stubs), the more you’re using ‘real’ data and the more the stubs are being removed in favor of the real deal.
If you’re rely on third party services, stubbing them out is a great way to keep on working while they fix their servers.
Great post. One tip: You could perhaps use some code format, as it reads a bit tough.
January 21st, 2012 at 10:21 am
A slight confusion over terminology, by “mocks” you mean hard-coded stubs? Otherwise, a good point.
January 21st, 2012 at 7:38 pm
The correct answer would be “depends”. They are mocks in my tests, but they are stub(s) when running the real application. This way I can run the application, see how it behaves.
In this case, I had data that would eventually be taken from a 3rd party webservice. But 90% of the time it was stubbed. Only at the last moment I actually called the webservice layer (which I knew was working, because it was tested on its own) and it all worked flawlessly.
So in short:
1. First the view (JSP ) shows a stubbed view object (ie, just showing data
2. Then the view object got created by a mapper. THe mapper would be returning the stubbed VO first
3. Actually implement the mapper
4. Stub the result from the webservice, since the mapper works (ie, tested) it still shows me the same result
5. The webservice method is now returning a stubbed result. The ‘web application’ basically is finished. Now its time to get the webservice client working.
Basically from there I would be implementing the webservice practically the same way. I had an integration test to make sure it really worked. Once that worked, I could use the actual implementation and it worked! 🙂
January 20th, 2012 at 5:36 pm
When I teach TDD to people unfamiliar to unit testing, I make sure they understand the point your making. I typically reference to this as writing the 3 A bottom up: start with Assertion – what do you want to achieve? Then the Act – what’s going to achieve this? Then Arrange as needed.
The business value lie in assert+act, so that should be the focus when writing a test = write the test bottom up.
January 20th, 2012 at 9:32 pm
I absolutely teach everyone that the output of the system is what matters, so start there. This is also why I teach writing tests starting with the assertion: focus on what you want to check, then figure out what you need to compute it. This is also why I teach designing starting with the client: focus on what the client needs, then figure out how to provide it simply. This avoid unnecessary code.
It works.
January 20th, 2012 at 10:26 pm
Yes, we did say it before 🙂
January 20th, 2012 at 10:27 pm
but a good post, nonetheless…
January 22nd, 2012 at 10:23 pm
Interesting idea, thanks Chris! I’ll try it out next time when I have a chance.
January 31st, 2012 at 12:01 am
Chris,
Shouldn’t we call that approach to TDD “outcome first” rather than “output first” ?
To me a winning board (or a tie board) is the outcome of a game of TTT, not necessarily the (only) output. If we see the game as a product, from a customer perspective, wouldn’t there be other outputs the customer is interested in ? What about a game in progress ? What about a blank board (first thing user sees when he logs on to the game) ?
Even if it so happened that no user of the TicTacToe product ever managed to finish a game, wouldn’t they still need those outputs in the first place ?
The kind of TDD you describe certainly works for programs that have a single identified outcome, such as computations that produce one result, games with a winner, etc. But we know this is not the case with all programs.
Anyway, very interesting article, makes me want to try it that way. And I’d be really interested in seeing your actual code 😉
February 5th, 2012 at 1:41 pm
[…] du TDD en sa basant sur les sorties plutôt que les entrées comme indiqué dans l’article TDD and Real Options. Nous entraînerons sur le défi tu […]
February 5th, 2015 at 9:37 pm
[…] TDD avec real-options sur l’exercice Elephant Carpaccio […]