BDD

Personal Behavior-Driven Development

by on August 19, 2013 12:07 pm

This year I was fortunate enough to attend the KCDC conference here in lovely Kansas City. One of the sessions I attended was on Behavior-Driven Development. I have attended several BDD sessions before and have enjoyed each one of them, but there was one stated question that set this one apart from the others. After learning of all the benefits of using BDD in one’s practice and becoming excited to start such a wonderful discovery, what happens if you won’t have any frameworks or management buy-in to support your mission?

As the BDD sessions indicate, frameworks such as Cucumber and JBehave gives the Agile team a way to create testing scenarios in a plain text format. So how do you set out on your own and what BDD principals can you implement on a personal development level?

Since BDD is an extension of Test-Driven Development, is it easy enough to use the principles and keywords of BDD down to the unit test level. Bringing BDD down to this level starts with following the naming template Dan North recommends for unit test method names.

At some point or another, we have all used the test class generator in Eclipse to save some time. It does give you a pre-populated class that prepends the word test in front of all visible method names, but is that time-saving or helpful in the long term? Is it easy to tell what testCalculateCost() tests for? You will eventually add more test cases for that particular method. How will you differentiate the method names for each additional test case?

Dan North recommends using sentences based on behaviors to describe the test. The test method testCalculateCost() would become testShouldFailForMissingBillingDate(). Dan also recommends using the word “behaviour” in favor of the notorious keyword “test” when describing what to test next. It is more natural to determine the behaviours of calculateCost() and to compare the next behavior to the existing behaviors to eliminate the gaps. The next natural behavior to test for may be the behavior of a missing due date with testShouldFailForMissingBillingDueDate().

Along with using the naming conventions suggested by Dan North, the session demonstrated how to organize the behavioral test class to mimic a BDD test scenario. As with BDD scenarios written for JBehave to parse, given/when/then BDD keywords are used to help construct and organize what is needed in the test class. These BDD keywords replace the arrange/act/assert keywords commonly used in plain unit tests.

Unit to BDD test keyword translation:

Unit Test Keyword → BDD Keyword
Arrange/Assemble → Given
Act → When
Assert → Then

While developers who are not on an Agile team can still use this style of writing behavioral tests, not starting with a user story can add to the learning curve. It is easier to translate a user story that contains the same structure as the finished personal BDD tests than a bullet point list of requirements. We will use a very basic user story along with a couple BDD test scenarios to show how similar the user story, BDD test case, and personal BDD test class are.

Example

We are working on a user story to add functionality to a Sudoku game to allow the user to verify if the numbers picked are correct during an in-progress game. Following BDD practices, the game functionality has not yet been implemented.

Story: Verify the board.

In order to verify the picked numbers
As a game player
I want the game to verify my picked numbers.

A BDD framework would accept something like this:

Scenario 1: A player who wants to know if they have incorrect numbers
Given a player who has a game in-progress
    When the board has all correct numbers
the player verifies the board
Then the board should be returned verified as correct

Scenario 2: A player who wants to know if they have incorrect numbers
Given a player who has a game in-progress
        and the board has all correct numbers
When the player picks an incorrect number
Then the board should be returned verified as incorrect
     and the incorrect number will be flagged as incorrect

Since we are back from the conference and in our BDD-less world, we will have to use our own creative process to fill in the guts of our personal BDD test class. At first, testing with a behavioral approach and not producing tests based on method names of the test fixture will be a little more difficult and time consuming, until this way of thinking is learned. It wasn’t an easy tread transitioning to a TDD world, but at least this will be an evolutionary step.

With this, we can start building our new personal BDD test class to test the behaviors of the verify method using JUnit 4.

Following what Dan North recommends, we can use the name SudokuBoardServiceSolveBehavior as our test class.

public class SudokuBoardServiceVerifyBehavior {
	...
}

As we fill out our test class using personal BDD, we will use the structure and the keywords of
given/when/then similar to what is in Scenario 1 and 2. While we won’t have the scenarios, they do help conceptualize the structure and organization of the test class.

The keyword given will be used for the test fixture generation methods. The method name will help define the test fixture and the scope of the acceptance tests. The given method will be annotated with JUnit’s @Before annotation and will be in the shared data. In our scenario, we want to start with a board partially filled with correct numbers.

public class SudokuBoardServiceVerifyBehavior {

	@Before
	public void givenCorrectBoardNumbers() throws Exception {
    		//stub the board
   	 	board = TestBoardFactory.createPartialBoardWithCorrectNumberes();
    		//setup the service
    		service = new SudokuBoardService();
	}
}

Next, the when methods contain the executable steps to take on the test fixture. Depending on the number of different behaviors to test, you may have several when methods for the single given method.  Each when can cover a BDD test scenario.  The when methods will be annotated with JUnit’s @Test.

public class SudokuBoardServiceVerifyBehavior {
	….
	@Test
	public void whenUserPicksCorrectNumber() {
   	 	//pick correct number
   	 	board.setNumber(POS_X,POS_Y,5);
    	}

    @Test
	public void whenUserSelectsInCorrectNumber() {
   	 	//pick incorrect number
   	 	board.setNumber(POS_X,POS_Y,4);
	}
}

Now we have the behaviors being performed on the test fixture. The last step is to find out what happened. Did we implement the requirements as expected? We will soon find out with the then methods. The more complicated the system, the more thens you will have as there will be more assertions to make about a behavior. For clarity and descriptiveness, you will have one assert per then. When you find that a unit test fails, you will know immediately and understand why the test failed. The method name will describe what we are asserting for. The when methods will be the ones responsible for passing control their respective then outcomes.

public class SudokuBoardServiceVerifyBehavior {
	private SudokuBoard board = null;
    	private SudokuBoardService service = null;
	private static int POS_X = 0;
	private static int POS_Y = 0;

	@Before
	public void givenCorrectBoardAndCorrectNumbers() throws Exception {
    		//stub the board
   	 	board = TestBoardFactory.createPartialBoard();
    		//setup the service
    		service = new SudokuBoardService();
	}

	@Test
	public void whenUserSelectsCorrectNumber() {
   	 	//pick correct number
   	 	board.setNumber(POS_X,POS_Y,5);
    		thenTheBoardIsVerifiedAsCorrect();
	}

	@Test
	public void whenUserSelectsInCorrectNumber() {
   	 	//pick incorrect number
   		board.setNumber(POS_X,POS_Y,4);
 		thenTheBoardIsVerifiedAsInCorrect();
    		theTheIncorrectNumberIsFlaggedAsIncorrect();
	}

	private void thenTheBoardIsVerifiedAsCorrect() {
   		service.verify(board);
   		assertTrue(board.isCorrect());
	}

	private void thenTheBoardIsVerifiedAsInCorrect() {
   		service.verify(board);
   		assertFalse(board.isCorrect());
	}

	private void thenTheIncorrectNumberIsFlaggedAsIncorrect() {
   		assertTrue(board.getNumber(POS_X,POS_Y).isCorrect());
	}
}

So what just happened here in order to bring BDD to the personal level?

You just became the framework replacement. You just translated the set of business requirements into unit tests. The only difference is that you used JUnit annotations instead of the set of annotations from Cucumber or JBehave. While these behavioral tests in no way compare to the value of what a full BDD infrastructure provides, we were able to introduce BDD principles and structure to a personal level. Personal BDD still provides the benefits of using BDD principles to focus on behaviors that directly contribute to business outcomes. Personal BDD will aid in writing unit tests that produce communicable evidence to the developers that the behavioral aspects of the system are working. Testing becomes more descriptive with better test class and method naming conventions.

To stay inline with BDD principles, the tests are still nicely automatable. Once all the tests pass, there will be a fully implemented business function protected with functional tests.
— John Hoestje, asktheteam@keyholesoftware.com

  • Share:

3 Responses to “Personal Behavior-Driven Development”

  1. I like this translation. It reinforces the fact that development strategies can almost always be implemented without specialized frameworks. Just have to be creative!

  2. […] Testing: Defining the right “Unit”Blog: A Dungeon Master’s Guide to SCRUMBlog: Personal Behavior-Driven DevelopmentBlog: Our checklist for improving mobile […]

Leave a Reply

Things Twitter is Talking About
  • ICYMI: we've released a demo version of #GrokOla which is open to the public. Try out its features & capabilities - http://t.co/O4ladowmFU
    July 4, 2015 at 3:05 PM
  • Happy 4th of July from the Keyhole team! We hope that you have a happy and safe holiday with your family and friends.
    July 4, 2015 at 9:55 AM
  • Let's talk testing. Here are common challenges #Agile teams face when writing automated tests & how to overcome them: http://t.co/DrKbNZJcE0
    July 3, 2015 at 11:06 AM
  • #GrokOla users get free educational tutorials. But lucky you, we've released some to the public. #JavaScript primer - http://t.co/nIR9XiWY6O
    July 3, 2015 at 10:55 AM
  • Being able to isolate debugging techniques can help make you a better debugger. Here's Time-Oriented #Debugging http://t.co/UplJgP4VzC
    July 2, 2015 at 10:50 AM
  • RT @zachagardner: @zachagardner has declared it is @ChipotleTweets day at @KeyholeSoftware . You have been warned 🐓🐖🐄
    July 2, 2015 at 10:09 AM
  • Current state of random number generation & the differences in how #Java & #JavaScript approach it - http://t.co/5tBKNXnu8T #security
    July 1, 2015 at 2:45 PM
  • Woohoo - 600 followers! Thanks, everyone. We'd love to ask you - what type of tweets / dev content would you like to see more of from us?
    July 1, 2015 at 10:38 AM
  • We would like to welcome Dallas Monson to the team today! Dallas is a Senior Architect focused on UI/UX and #JavaScript. Welcome, Dallas!
    July 1, 2015 at 8:35 AM
  • Good introduction to TypeScript - http://t.co/0N22fVpAHt Plus, how to approach modularization in #TypeScript - http://t.co/wxRWGBj3Uh
    June 30, 2015 at 3:25 PM
  • .@mrbristopher just delivered a new S911 Night Drone to James Hayes, winner of our #kcdc15 giveaway! Congrats, James! http://t.co/RriJIxubH2
    June 30, 2015 at 11:35 AM
  • It feels like primitives could have been left out of the initial implementation of #Java. See why - http://t.co/A8ChCBHXJO
    June 29, 2015 at 4:05 PM
  • Developers in a bounce house! I repeat, developers in a bounce house! We had a blast at our 1st company picnic. Pics: http://t.co/XIqs7ECUst
    June 29, 2015 at 1:40 PM
  • New #SpringBatch tutorial from @jhackett01: Spring Batch – Replacing XML Job Configuration With JavaConfig http://t.co/PmdXnriKQu #java
    June 29, 2015 at 11:46 AM
  • We had such a fun time at the Keyhole company picnic! Pictures to come, including some of our developers in the bounce house. #loveourteam
    June 29, 2015 at 8:41 AM
  • In #JavaScript, how do we harness the power of callbacks without the confusing mess of nested functions? Promises - http://t.co/j1gAJ9hi3D
    June 29, 2015 at 8:40 AM
  • .@zachagardner We are so happy that your family attended! This will definitely need to be repeated every year!
    June 28, 2015 at 8:14 PM
  • Thank you to all on the Keyhole team who came to our first inaugural company picnic! Wonderful food, family and bounce house fun!
    June 28, 2015 at 7:50 PM
  • Debugging is a challenging part of being a programmer. We have a tutorial series to help, with a #JavaScript focus - http://t.co/rfhjJo64P7
    June 27, 2015 at 1:45 PM
  • We love #KCDC15! @PinsightMedia's James Hayes just was drawn as the winner of the @KeyholeSoftware drone giveaway. Stop on by the KHS booth.
    June 26, 2015 at 2:24 PM