One problem with given-when-then... the answer... "Other Examples Include"
As I've mentioned before, in acceptance test driven development, I use the Given/When/Then structure for writing acceptance tests. This approach is attributed to Dan North and Joe Walnes presentation at XPDay 2006.
For example, let's consider a test for a story around logging in (I know - I always use this but it's something most people have experience of):
Given that the user has opened the application
and the user amarcano is registered with the password this!Is4Password
and the user has not attempted a failed login previously
When the user attempts to login with username amarcano and password this!IsN0tThePassword
Then the user Antony Marcano should not be logged in
and the system should display the message incorrect username or password
This is a simple case of the user not being allowed to login if they enter the wrong password.
(Notice how I write in terms of the activity, not the tasks.)
That's cool... but what about other variations on the incorrect password that you'd want to test... like "this!Is4Passwor" or "this!Is4Passwordd" or "thisIs4Password" or simply leaving the password blank. The behaviour is equivalent (i.e. an equivalence class) but they are still variations we'd want to test.
Other Given/When/Then illustrations show you repeating the same test with each variation...
Given that the user has opened the application
and the user amarcano is registered with the password this!Is4Password
and the user has not attempted a failed login previously
When the user attempts to login with username amarcano and password [BLANK]
Then the user Antony Marcano should not be logged in
and the system should display the message incorrect username or password
Given that the user has opened the application
and the user amarcano is registered with the password this!Is4Password
and the user has not attempted a failed login previously
When the user attempts to login with username amarcano and password this!Is4Passwor
Then the user Antony Marcano should not be logged in
and the system should display the message incorrect username or password
...and so on.
I've found that this results in a lot of clutter making it hard to see at a glance what other examples that have the equivalent outcome might have been missed.
To address this, for some time I've been using this approach...
Given that the user has opened the application
and the user amarcano is registered with the password this!Is4Password
and the user has not attempted a failed login previously
When the user attempts to login with username amarcano and password this!IsN0tThePassword
Then the user Antony Marcano should not be logged in
and the system should display the message incorrect username or password
Other examples of this login scenario include:
username password amarcano BLANK amarcano this!Is4Passwor amarcano this!Is4Passwordd
If you are using FIT or FitNesse, you can use a DoFixture to write this... each of the statements is a method (the 'Then' line can be implemented as a synonym for 'Check') and the 'otherExamplesOfThisLoginScenarioIncludeColon()' in your extension of the DoFixture returns a column fixture that simply calls the methods in your DoFixture extension (I'll post some code samples later when I have time)...
| Other examples of this login scenario include: | |||
|---|---|---|---|
| username | password | login state? | expected message shown? |
| amarcano | BLANK | not logged in | yes |
| amarcano | this!Is4Passwor | not logged in | yes |
| amarcano | this!Is4Passwordd | not logged in | yes |
I hope you find it useful...
Oh, there's one more thing... I recently showed this to Liz Keogh, key contributor to JBehave, and she likes it so much that she's hoping to add this approach as a feature to the recently released JBehave 2.0 (congrats on getting the release out Liz :-)... I'm looking forward to seeing "other examples include" in JBehave soon :-)
