Driving Development with User Stories and BDD - Real World .NET, C#, and Silverlight: Indispensible Experiences from 15 MVPs (2012)

Real World .NET, C#, and Silverlight: Indispensible Experiences from 15 MVPs (2012)

Chapter 14

Driving Development with User Stories and BDD

by Scott Millett

If I could offer you one piece of advice (apart from always wear sunscreen), it would be to do your utmost to understand your domain inside and out, share your stakeholder's visions and goals, and sit as close to your domain experts as possible. If you follow my advice, then you should find software development nice and easy. Okay, so you have to learn the framework and language syntax, but after you master them, everything else should be relatively simple.

So, if development is easy, why do so many projects get in trouble and fail to deliver what the business needs? The reason that projects fail is not because of a lack of programming ability or technical expertise, but rather because of a lack of understanding, communication, and business knowledge.

This lack of understanding stems from how developers capture knowledge of the problem domain they work in. Put another way, if developers and customers cannot effectively communicate, then even with the most accomplished programmers in the world, you ultimately cannot satisfy the needs of your customers.

This chapter is about refocusing efforts on how requirements of a system are captured, how customers communicate those requirements through user stories, how development can be driven from the language and features through behavior-driven development, and, ultimately, how software can be delivered to meet the needs and expectations of your customer.

Capturing Requirements as Features with User Stories

A user story is typically one or two sentences, written in plain language on an index card, describing a feature of value to the business. You will learn that if you employ user stories to capture the features of a system as a direct replacement for more formal, all-encompassing requirements documentation, you can re-address the balance placed on communication during software development. The shift to emphasizing the importance on communication over detailed specifications can also help to commit and underline a customer's responsibility to the success or failure of the project.

Through regular and frequent conversations with the people the software is being built for, greater knowledge about the problem domain can be gained. This ultimately leads to a development team that is far more aligned and in sync with customer expectations and, therefore, capable of meeting the needs of the customer.

Before you can understand exactly what a user story is, you need to understand what problems they solve when compared to the traditional upfront requirements documentation.

Problems with Formal Requirements Documentation

In theory, extensive documentation is great. Gather all requirements up front, create a document detailing exactly what is needed, hand it all to the development team, wait 6 months, and have them deliver the product that you want. In reality, however, for all except the most rigid of projects, this process fails.

One of the most important artifacts of the upfront design approach to development is the requirements document — the Bible, if you will. A funny thing happens when all development is focused on what is contained within the requirements Bible. The document becomes the contract for the project. If it's not in the requirements document, it isn't done. The document controls development and prevents communication between the development team and the customer, which leads to issues and the famous phrase, “It's what I asked for, not what I need.”

Following are some of the major problems with requirements documents:

· Documents are open to interpretation.

· Large requirements documents act as an incapacitating contract.

· Customers do not know what they want.

· Customers change their minds.

· Developers don't understand the requirements.

· Customers are not sure of the details of all requirements at the start of a project.

What is needed is a move away from trying to capture every conceivable piece of information before a project starts, and toward a development team that understands what the customer wants to achieve, who will work closely with the customer as it discovers the details, and who will adapt to the customer when requirements change as the project progresses and more knowledge is gained.

User stories shift the focus from writing large, upfront documentation (which can act as an inflexible and somewhat incapacitating contract), toward communication through talking, and talking often.

Using User Stories to Focus on Business Value and Promote Communication

In short, a user story is a short description of a unit of functionality that represents value to the customer. User stories are a more effective and lean way to capture requirements with just enough information to determine complexity and estimate effort to deliver.

The lack of details in user stories is one of the biggest benefits. Rather than trying to write down all requirements in one session, and hoping the customer has the answers to all your questions, you instead capture the essence of the feature, and commit to having a conversation with the customer at a later date to discuss the details.

User stories are typically captured on index cards following the template shown in Figure 14.1.

Figure 14.1 Example of user story captured on an index card

14.1

User stories must include the following:

· They are understandable by all and written in the language of the customer.

· They provide enough detail to estimate. When the story is worked on, a conversation is needed for the details.

· They are testable, enabling the development team to know when it is complete.

Later in this chapter, you will run through an exercise that utilizes user stories to capture requirements for a simple game of Tic-Tac-Toe.

note

For more information on user stories, see User Stories Applied: For Agile Software Development (Boston: Addison-Wesley Professional, 2004) by Mike Cohn.

User stories are great for capturing features, but to ensure the feature is developed and meets the needs of the customer, developers must understand the acceptance criteria of a business feature (in other words, how to know when a feature is done).

Feature Scenarios and Story Acceptance Criteria

When capturing requirements with user stories, it's a great idea to use the reverse side of the index card to jot down acceptance criteria and information that can assist you when working and talking to the customer at a later date.

After you note the initial acceptance criteria, you can produce acceptance scenarios to further confirm knowledge of the problem domain, and also use as tests to ascertain when the feature has been developed.

Scenarios are typically written in the “Given, When, Then” template, as shown here:

Given some initial context

When an event occurs

Then ensure some outcomes

Now apply the template to the “win a game” feature of Tic-Tac-Toe, and specifically the criteria that confirms a diagonal win.

Given that I have started a game of Tic-Tac-Toe

And the following moves have been played

X | O |

----------------

O | X |

----------------

| |

When Player X places a token at the coordinate 2, 2

Then Player X should be the winner

Because of the plain language that is used, describing acceptance criteria in this format makes it trivial for developers and customers to understand the features. It also makes it easy for the development team to know when it has completed a unit of work because it is simple for them to test against the clear acceptance criteria.

Now that you understand how to capture features using user stories, and how to define acceptance criteria, you can focus on turning those requirements into working software, safe in the knowledge that your development effort is driven with a mindset focused squarely on delivering value to the business.

But where do you start to develop? Maybe you should use TDD to drive out the system from the inside, starting with the smallest unit of functionality… or maybe there's a more effective way.

The Shortcomings of TDD

Test-Driven Development (TDD) is the methodology of driving the design of a system through writing a failing test, writing the code to get the test to pass, refactoring to a simpler design, and repeating until the application is built. TDD focuses on unit testing, which involves testing the smallest pieces of functionality. When driving design with this level of detail, you can easily become lost in the technical aspects of what you are trying to achieve, rather than focusing on the overall aim and behavior of the system.

TDD can place too much emphasis on the mechanics of a component in your application — in other words, how it does, rather than what it does. Developers must be disciplined when working with TDD to ensure that they always have the bigger picture in mind when they decide about the low-level technical details of a feature. For example, customers don't care about the intricate details of how data is stored, but rather that it is available when they use the system.

TDD still has a place in driving the development of a system. However, a more focused methodology is required to wrap the TDD process and emphasize the behavior of a system, rather than technicalities — or put another way, the “what it does” rather than “how it does it.”

Focusing on Behavior with BDD

Behavior Driven Development (BDD) has evolved from TDD, with a good dollop of Domain Driven Design (DDD) mixed in. BDD helps to keep focus on the behavior of a system by using the features of TDD, as well as the shared ubiquitous language of the business domain. BDD drives the design of a system using the desired features of the customer in a language that everyone can understand, and that clearly communicates the benefit and purpose of features under development.

With a better understanding of the domain through features, developers can incorporate this shared language into the code base, which further helps to concentrate efforts on what the system is trying to achieve, rather than how it will achieve it.

How the system will accomplish what it is designed to do (that is, the technical details) is still important, and this is where TDD comes in. Used together with BDD, they form “outside-in development.”

Outside-In Development

Outside-in development is the process of driving the design of an application from the point of view of the customer. Customers typically measure the success of an application through the user interfaces (UIs) that they leverage to interact with it. With this in mind, outside-in development utilizes BDD to drive the design of the code from the UI (or the outside), and then employs TDD to discover the objects, services, and other code that form the domain of the application (or the inside).

Figure 14.2, the “BDD figure of 8” shows the process of BDD and outside-in development The “figure of 8” name comes from the two circles placed upon one another representing the life cycles of driving application and object behavior.

Figure 14.2 The “BDD figure of 8” diagram showing the process of BDD and outside-in development

14.2

The process of outside-in development begins with a feature selection, such as the following:

In order to place an order

As a customer

I want to add products to my basket

Then, a scenario is selected, such as the following:

Given I am on a product detail page for a hat costing $5

When I click the add to basket button

Then I should have 1 hat in my basket

And then basket total should be $5

The next action is to write a failing scenario step. In this instance, you would create code that confirms that the product detail page can display. For the page to display, you may discover that, in a web scenario, you need a new controller and controller action, and maybe a repository to retrieve the details of the product displayed.

You drive the design of the various components needed to display the page using TDD. After all the code is written to satisfy the scenario step, you can move on to the next step that handles the action of adding the product to the basket. Again, you drop down into TDD to drive the design and development of the low-level details that support the steps behavior.

This process is repeated until all steps of the scenario are passing, at which point you move on to the next scenario. After all scenarios are complete, you move on to the next feature until all features are complete.

Using the outside-in approach, you can quickly produce working code that is driven directly from the requirements and needs of the customer. This is achieved by working in vertical slices of functionality, rather than layers of responsibilities. Working from the outside in also enables customers to provide feedback on how the system behaves from an early stage, allowing developers to fine-tune the design and behavior of the system to better meet the needs of the customers. Leaner and more focused domain models built from features help to adhere to the “You Ain't Gonna Need It” (YAGNI) principle, and avoid unnecessary and overly complex domain hierarchies.

You should now have a good understanding of what BDD is all about. However, to use it to drive your development efforts, you must think about how you write your code. The simplest way to accomplish this is to use a BDD framework that guides you to turn your stories and acceptance criteria scenarios into working code.

Turning Features into Code Using BDD Frameworks

Some great frameworks support BDD in the world of .NET and beyond. Let's take a look at a couple of choice cuts.

Using NUnit in a BDD Style

NUnit is one of the most popular unit testing frameworks for .NET, and it's just as effective when used as a runner for BDD specifications. You can get NUnit by navigating to www.nunit.org/. The following code snippet is from the exercise that you tackle later in this chapter, which you can find in the code download on this book's companion website (www.wrox.com):

public class when_player_X_makes_the_first_move : with_a_TicTacToeGame

{

public override void Given()

{

// No context to set up

}

public override void When()

{

SUT.place_token_at(new Coordinate(0, 1));

}

[Then]

public void I_should_be_told_that_player_O_is_next_to_go()

{

Assert.That(SUT.next_player_to_move, Is.EqualTo("O"));

}

}

To align the NUnit specification code with the “Given, When, Then” syntax, an abstract base class can provide a template method. The SUT (System Under Test) property is created in the set-up method of the base class that initializes an instance of the TicTacToeGame object.

MSpec

MSpec is short for Machine.Specifications and is available from the project home page at https://github.com/machine/machine.specifications. According to the website, MSpec can be described as follows:

…a Context/Specification framework geared towards removing language noise and simplifying tests.

MSpec utilizes lambdas to produce code that is as free from noise as possible. When you get your head around the funny syntax, you will find MSpec to be a powerful BDD framework.

The following code snippet shows the equivalent MSpec version of the specification example used to demonstrate the NUnit code, which, in turn, is based on the exercise that you do later in this chapter (and available on this book's companion website at www.wrox.com):

[Subject(typeof(TicTacToeGame), "Game Play")]

public class when_player_X_makes_the_first_move : with_a_TicTaceToeGame

{

Because of = () => SUT.place_token_at(new Coordinate(0, 1));

It should_say_that_player_O_is_next_to_go =

() => Assert.That(SUT.next_player_to_move, Is.EqualTo("O"));

}

Reporting is a great feature of MSpec. When running the specs, MSpec produces some readable output, as shown in Figure 14.3, which can be handed straight to your customer for verification.

Figure 14.3 Output from MSpec

14.3

Ruby Cucumber and the Gherkin Domain Specific Language (DSL)

The Cucumber BDD tool for Ruby (http://cukes.info/) parses plain-text scenarios written in the Gherkin syntax form into code that runs step definitions that you produce. The following snippet shows an example of the Gherkin syntax that Cucumber understands:

Feature: Game Play

In order to play a game of tic-tac-toe

As a player

I want to know the state of play

Scenario: Alternating moves

Given that I have started a new game

When Player "X" places a token at the coordinate "0","1"

Then I should be told that player "O" is next to go

As a developer, your job is to create the step definitions that Cucumber requires to prove the acceptance criteria.

The following code snippet shows some Ruby code that defines the step definitions:

Given /ˆthat I have started a new game$/ do

pending

end

When /ˆplayer X places a token at the coordinate$/ do

pending

end

Then /ˆI should be told that player O is next to go$/ do

pending

end

Even though the Cucumber framework is for Ruby, it can still be utilized when working with .NET. Testers who have little programming experience and are verifying acceptance criteria may find it easier to learn the lean Ruby scripting language to run acceptance tests, rather than working in C#. Also, seasoned C# developers may want to leverage the mature Cucumber framework to verify that acceptance criteria have been satisfied.

SpecFlow

SpecFlow (available to download from www.specflow.org/) is the .NET version of the Cucumber BDD framework, which stays faithful to the Gherkin syntax. Features and scenarios are written in the exact same way as with the Cucumber tool, as shown in the following code snippet:

Feature: Game Play

In order to play a game of tic-tac-toe

As a player

I want to know the state of play

Scenario: Alternating moves

Given that I have started a new game

When Player "X" places a token at the coordinate "0","1"

Then I should be told that player "O" is next to go

SpecFlow uses a custom tool to parse the plain-text file into code that the .NET Framework can understand. The code produced by SpecFlow expects to find step definitions that match the steps of the plain-text scenarios. As with Cucumber, your job is to provide those step definitions and assert the behavior, as shown in the following code snippet:

[Binding]

public class GamePlaySteps

{

[Given(@"that I have started a new game")]

public void GivenThatIHaveStartedANewGame()

{

GameStorage.Current = new TicTacToeGame(new

TicTacToeWinningCondition());

Assert.That(GameStorage.Current.is_in_play, Is.True);

}

[When(@"Player ""(.*)"" places a token at the coordinate

""(.*)"",""(.*)""")]

public void WhenAPlayerPlacesAToken(string player, int x_coordinate,

int y_coordinate)

{

GameStorage.Current.place_token_at(

new Coordinate(x_coordinate,

y_coordinate));

}

[Then(@"I should be told that player ""(.*)"" is next to go")]

public void ThenIShouldShouldBeToldThatTheNextPlayerIs(string player_token)

{

Assert.That(GameStorage.Current.next_player_to_move,

Is.EqualTo(player_token));

}

}

SpecFlow is the best BDD framework for .NET when developing in the outside-in method. Its plain text (to describe the features and scenarios) becomes an artifact of the Visual Studio solution and ensures that it acts as living documentation of the behaviors of the system (which can be understood by customers with no technical knowledge).

To provide you with real-world experience of BDD, let's now work through a small code kata that utilizes the SpecFlow BDD framework.

The Tic-Tac-Toe BDD Kata

Now that you have read about the benefits of capturing feature requirements as user stories, and how by applying the BDD process you can drive your development and keep focus on delivering business value, it's time to see it in action. For this small code kata, you will develop an implementation of the classic game Tic-Tac-Toe (or naughts and crosses, if you're from my side of the pond). Pretend, however, that you have never heard of this game (even better if you haven't), and, as a diligent developer, your first course of action is to understand the domain better by capturing the features of the game.

note

Code kata is a term coined by Dave Thomas, co-author (with Andrew Hunt) of the book The Pragmatic Programmer: From Journeyman to Master (Boston: Addison-Wesley Professional, 1999), in a bow to the Japanese concept of kata in the martial arts. A code kata is an exercise in programming that helps hone your skills through practice and repetition.

Capturing the Tic-Tac-Toe Features with User Stories

The best way to capture the features of a domain that you have no idea about is to talk to a domain expert, and your Tic-Tac-Toe expert is Mark.

You: “Hi Mark, I am going to be developing the Tic-Tac-Toe game. Can you tell me what your vision for the game is?”

Mark: “Sure. We want a simple console-based game for two players.”

You: “Sounds great. Before we get into the details of the application, could you tell me how the game is played? I'm afraid I have never played before.”

Mark: “Okay, no problem. Tic-Tac-Toe is a game for two players, played on a 3 × 3 grid. The first player to get three in a row wins.”

You: “Three what?”

Mark: “Tokens. You have a player with an X token and a player with an O token.”

You: “So, to win a game of Tic-Tac-Toe, a player must get three tokens in a line. Cool. That sounds like my first user story.” (See Figure 14.4.)

Figure 14.4 User story describing the winning a game feature

14.4

You: “So, is this vertical? Horizontal? Or diagonal?”

Mark: “All of the above! As long as a player has three tokens in row, it doesn't matter if it's on a row, on a column, or from one corner to another.”

You: “Ah, I understand. I will jot that down as acceptance criteria on the reverse side of the card for the user story.” (See Figure 14.5.)

Figure 14.5 Acceptance criteria for winning a game feature

14.5

You: “Okay, what else do I need to know?”

Mark: “Well, you might want to jot down that you need a 3 × 3 grid to play.”

You: “Ah, good call, I almost forgot. I will also draw a simple grid to visualize the game board.” (See Figure 14.6.)

Figure 14.6 User story describing game grid feature

14.6

You: “So, can you place your token on top of another player's token and replace it?”

Mark: “No, that is not a valid move. Tokens can be placed only on empty squares within the grid.”

You: “Okay, I will just make a note of that.” (See Figure 14.7.)

Figure 14.7 Acceptance criteria for game grid feature

14.7

You: “Okay, I think I have enough information on the rules of the game. How will the game start and how should we display the state of the game? Do you want players to be able to input their names?”

Mark: “Oh no, nothing as fancy as that. Perhaps just a little welcome message with some instructions on what to do could be displayed on the screen.”

You: “Great, how about taking input from the players?”

Mark: “Can we just have them enter a grid reference or box number into the console?”

You: “Yes we can.”

Mark: “Basically after every move we need to update the display on the console application, what we show to the players and how they interact is very important.”

You: “I understand. I will capture that as another story.” (See Figure 14.8.)

Figure 14.8 Story describing the display of the game

14.8

You: “And I will add some notes to the back of the card on the welcome screen and inputting moves.”

Mark: “Also, the players need to view the board so that they can plan their next move.”

You: “Right, I understand. So, before each move they can take a look at the board so that they know where to place their next token. Cool! I will add that as more criteria for displaying the state of a game.” (See Figure 14.9.)

Figure 14.9 Acceptance criteria for story describing the display of the game

14.9

You: “Oh, one thing that I didn't ask when we were talking about the rules of the game was about drawing a game, is this possible?”

Mark: “Yes. It is possible to have a draw. If all spaces on the board are used, and no more tokens can be placed, then the game is a draw.”

You: “Gotcha. I will capture that as another user story.” (See Figure 14.10.)

Figure 14.10 Story describing the drawing condition of a game

14.10

You: “Anything else?”

Mark: “Well, I guess for people who have never played the game before, it would be helpful to let them know whose turn it is.”

You: “Yes, and they would also need to know if the game has a winner or has ended in a draw. I will add these points as notes on displaying the state of the game story.” (See Figure 14.11.)

Figure 14.11 More criteria for the story describing the display of the game

14.11

Mark: “Yep, that sounds good.”

You: “So, who takes the first turn at the start of a game?”

Mark: “Traditionally player X is always the first to play.”

You: “Brilliant! I will make a note of that.” (See Figure 14.12.)

Figure 14.12 Even more criteria for the story describing the display of the game

14.12

You: “Lovely. I think I have enough user stories to start to work. Can you think of anything else?”

Mark: “No, I think you have it all.”

You should now have a much better idea of how you can use user stories to capture requirements. When capturing features as user stories, remember to do the following:

· Engage with the domain expert and capture features in the language of the customer, often referred to the ubiquitous language.

· Ensure that your stories are testable, can be estimated, and represent value to the business.

· Don't transcribe meetings. Capture just enough detail to understand a feature. Remember, user stories are reminders for conversations at a later date.

When you can't think of any more features, it's a good idea to go through some scenarios for each feature. This can help you to understand the feature at a more detailed level, as well as provide you with some acceptance criteria to test against.

Getting Started with the Project

To start this project, the first thing you must do is install SpecFlow. SpecFlow integrates with Visual Studio to turn your Gherkin syntax into code that the .NET runtime can understand. Navigate to www.specflow.org/, download, and run the installation package.

With SpecFlow installed, fire up Visual Studio and create a new solution named Wrox.BDD. Add the following class libraries to the solution:

· Wrox.BDD.Specs.UAT — This will contain your SpecFlow specifications based on your acceptance criteria. The UAT acronym stands for User Acceptance Tests. This class library is specifying the behavior of your application.

· Wrox.BDD.Specs.Core — This will contain your MSpec specifications specifying the behavior of your objects that support the behavior of the application.

· Wrox.BDD.Domain — This project will contain the domain of the Tic-Tac-Toe game, including all of the rules and game logic.

· Wrox.BDD.Ui.Console — This project is a Windows console application project and will contain all the presentation for the game.

Next, you must reference NUnit and SpecFlow from within your Wrox.BDD.Specs.UAT project, and MSpec, NUnit, and Rhino Mocks (a Mocking framework) from within your Wrox.BDD.Core project. The quickest way to do this is to use the NuGet package installer.

note

NuGet (formerly known as NuPack) is a free, Open Source, developer-focused package management system for the .NET platform. It simplifies the process of incorporating third-party libraries into a .NET application during development. You can download it from http://nuget.codeplex.com/.

To set up NuGet, click Tools → Extension Manager from within Visual Studio. When the Extension Manager dialog box appears, select the Online Gallery tab, and enter nuget in the search box. When found, select NuGet Package Manager, and then click Download to install the tool.

After installation, you must restart Visual Studio. When restarted, pull up the Package Manager Console window by selecting Tools → Library Package Manager → Package Manager Console.

When the Package Manager Console is available, in the drop-down menu, select the Wrox.BDD.Specs.UAT project as the default project, as shown in Figure 14.13. Type in the following command:

install-package SpecFlow

Figure 14.13 NuGet Package Manager Console dialog

14.13

Press Enter. After SpecFlow is installed, enter the following:

Install-package NUnit

NuGet pulls down the SpecFlow and NUnit packages to a local package folder at the root of your solution and also references the required assemblies in your Wrox.BDD.SpecFlow.Specs project.

Perform the same steps to add MSpec, NUnit, and Rhino Mocks to the Wrox.BDD.Specs.Core project by using the following commands.

For Rhino Mocks, use the following:

Install-package RhinoMocks

For MSpec, use the following:

Install-package Machine.Specifications

One last tool that is helpful when testing is TestDriven.NET from www.testdriven.net/. TestDriven.NET is an easy-to-use test runner that can run your Wrox.BDD.Specs.UAT project.

Scenario: Starting a Game

With your environment set up, you can start to work on your first specification. Create a folder within the Specs.UAT project named Features to store all of your features, and add a new feature named GamePlay.feature using the new template type that SpecFlow has installed. Then update the feature and scenario to match Figure 14.14.

Figure 14.14 The scenario for starting a game in SpecFlow

14.14

The feature is written to describe the expected behavior of the game from the user's perspective. It is the presentation and user experience that is being specified at this point.

As mentioned before, the features, scenarios, and steps are written in the Gherkin language. You must write the specifications in this language because, as soon as you save the feature file, SpecFlow will parse it and create a matching code file that contains test fixtures that rely on step definitions you will create in a moment. With me so far?

Okay, maybe an example will help. If you run the SpecFlow specs with TestDriven.NET or with NUnit, you will see the output as shown in Figure 14.15.

Figure 14.15 SpecFlow output showing the code template for the missing step definitions

14.15

What SpecFlow is telling you is that it was expecting to find methods for each of the steps in your scenario. If you think about it, that makes a lot of sense — you're expected to write the code and the step definitions to pass the scenarios. So, with this level-headed thinking, let's create some steps to satisfy SpecFlow.

Before adding code for the step definitions, let's pause for a moment to remind ourselves of the outside-in development methodology you will be following. You must drive development from the outside of your system — this means the presentation of the game of Tic-Tac-Toe. By driving design from this point of view, you will keep the development effort squarely focused upon application behavior. With that thought in mind, let's finally get to some coding.

It's a good idea to organize steps into logical groups, so add a new folder named Steps and a new class named GamePlaySteps. This will hold all steps relating to game actions. Copy in the code generated by SpecFlow, as shown in the following snippet:

note

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using TechTalk.SpecFlow;

namespace Wrox.BDD.Specs.UAT.Steps

{

[Binding]

public class GamePlaySteps

{

[Given(@"that I have started a new game")]

public void GivenThatIHaveStartedANewGame()

{

ScenarioContext.Current.Pending();

}

[Then(@"I should see the following displayed:")]

public void ThenIShouldSeeTheFollowingDisplayed(string multilineText)

{

ScenarioContext.Current.Pending();

}

}

}

Code file [GamePlaySteps.cs] available for download at Wrox.com.

Now, if you run the specs within your Specs.UAT project, you will find that they are skipped, and that you are told that one or more step definitions is not yet implemented. So, let's implement them.

To output the text to the screen, you must present a view of the game. Because this is a console application and, thus, stateful, unlike a web application, it makes sense to follow the Model-View-Presenter (MVP) pattern to organize the presentation logic.

Update the GamePlaySteps class with the following code. Remember that none of these classes exist. You are defining the API you want to work against from the outside in, or from the presentation to the domain.

note

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using TechTalk.SpecFlow;

namespace Wrox.BDD.Specs.UAT.Steps

{

[Binding]

public class GamePlaySteps

{

[Given(@"that I have started a new game")]

public void GivenThatIHaveStartedANewGame()

{

var fake_game_view = new FakeGameView();

}

[Then(@"I should see the following displayed:")]

public void ThenIShouldSeeTheFollowingDisplayed(string multilineText)

{

ScenarioContext.Current.Pending();

}

}

}

Code file [GamePlaySteps.cs] available for download at Wrox.com.

To start, you created a view, and, because this is a test environment, you create a fake view. The view will interact with a game presenter, and the game will start upon construction of the view. Now that you have an idea of how you want to drive the design of the system using the MVP pattern, you can create the presenter itself.

Add a new folder to the Ui.Console console project named Presentation. Within it, create a new class named TicTacToeGamePresenter with the following class definition:

note

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

private readonly GameView _game_view;

public TicTacToeGamePresenter(GameView game_view)

{

_game_view = game_view;

}

public void start()

{

}

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

Next, add the missing view interface to the same presentation folder, as shown in the following code snippet:

note

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace Wrox.BDD.Ui.Console.Presentation

{

public interface GameView

{

}

}

Code file [GameView.cs] available for download at Wrox.com.

You will need to update the Specs.UAT project to reference the Ui.Console project, and add a using statement for the presentation namespace.

note

You may have noticed the lack of the traditional I before the interface for the GameView. I have decided to drop the I prefix from my interfaces in order to discipline myself into thinking far more about the language I am using to convey an abstract concept in my domain. For years, I would blindly add an IXXXService to code without stopping to think about the language I was using. I now make it clear through language what is abstract and what is a concrete concept in my code base. Of course, a valid approach to prefixing an interface with an I might be to treat is as a verb (for example, ICalculateIncomeTaxForEmployees). It doesn't matter what naming convention you do or don't use. The most important point to remember is to make your code as readable as possible, and ensure that it communicates exactly what it does in the most natural manner.

Now, the compiler will still be complaining about the undefined FakeGameView. To stop it from bothering you, create the missing class as shown in the following definition and place it in the root of the Specs.UAT project:

note

using Wrox.BDD.Ui.Console.Presentation;

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this);

_presenter.start();

}

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

If you run the specs now, you will find that the first step completes, but the second is still skipped. Okay, so now you have the game started. The next step definition requires you to confirm that the welcome message is displayed to the view.

To share the game presenter and the view between steps, you will use SpecFlow's scenario context. This simply means that objects can be shared across steps that could exist in separate step definition classes. Create a new folder named StepHelpers and add the following code:

note

using Wrox.BDD.Ui.Console.Presentation;

using TechTalk.SpecFlow;

namespace Wrox.BDD.Specs.UAT.StepHelpers

{

public static class GameStorage

{

public static FakeGameView game_view

{

get { return ScenarioContext.Current["View"] as FakeGameView; }

set { ScenarioContext.Current["View"] = value; }

}

}

}

Code file [GameStorage.cs] available for download at Wrox.com.

The GameStorage class should be straightforward. If you're an ASP.NET/MVC developer, think of the ScenarioContext like the ASP.NET session object.

With the GameStorage class in place, you can update the GamePlaySteps class to save the fake view in one step, retrieve it in another, and use NUnit to assert that the expected text was displayed on the view.

note

using TechTalk.SpecFlow;

using Wrox.BDD.Ui.Console.Presentation;

using Wrox.BDD.Specs.UAT.StepHelpers;

using NUnit.Framework;

namespace Wrox.BDD.Specs.UAT.Steps

{

[Binding]

public class GamePlaySteps

{

[Given(@"that I have started a new game")]

public void GivenThatIHaveStartedANewGame()

{

var fake_game_view = new FakeGameView();

GameStorage.game_view = fake_game_view;

}

[Then(@"I should see the following displayed:")]

public void ThenIShouldSeeTheFollowingDisplayed(string multilineText)

{

var view = GameStorage.game_view;

Assert.That(view.display(), Is.EqualTo(multilineText));

}

}

}

Code file [GamePlaySteps.cs] available for download at Wrox.com.

Again, you have added some behavior that makes sense, namely the display method that would return what has been output to the screen. You are comparing this to what you expect to be outputted.

The display method only makes sense on the fake view, because the real view will simply display any output to the console window. This is why you will not add the method to the GameView interface.

Update the FakeGameView to include the new display method.

note

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

private StringBuilder _display = new StringBuilder();

public string display()

{

return _display.ToString();

}

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this);

_presenter.start();

}

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

Now that the IDE has stopped complaining about the missing display method, you can build and run the specs. You will find that you have your first logic error, hurrah! The welcome text that was expected is never written to the view. At this point, you can drop into the behavior of the objects (namely the presenter) to ensure that it is talking to the view as defined by the scenario step.

Before you start to code, what do you expect the presenter to do when it is told to start?

1. Display the welcome message on the view.

2. Prompt the player to make a move.

It's always a good idea to write out your assumptions and expectations before you start to write your specification within Visual Studio, so you can keep focused on behavior as you code.

Add a new folder named Presentation_Specs to the Specs.Core project, and then add a new class named when_starting_a_new_game with the following definition. You will need to add a reference to the Ui.Console project as well.

note

using System;

using System.Collections.Generic;

using Machine.Specifications;

using Rhino.Mocks;

using Wrox.BDD.Ui.Console.Presentation;

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(TicTacToeGamePresenter))]

public class when_starting_a_new_game

{

Establish context = () =>

{

game_view = MockRepository.GenerateStub<GameView>();

SUT = new TicTacToeGamePresenter(game_view);

};

private Because of = () =>

{

SUT.start();

};

private It should_send_a_welcome_message_to_the_view = () =>

{

game_view.AssertWasCalled(x => x.write_line(Arg<String>.Is.Anything),

a => a.Repeat.AtLeastOnce());

};

private It should_prompt_for_a_move = () =>

{

game_view.AssertWasCalled(x => x.get_coordinates_for_next_move());

};

private static TicTacToeGamePresenter SUT;

private static GameView game_view;

}

}

Code file [when_starting_a_new_game.cs] available for download at Wrox.com.

This is your first MSpec class. Let's quickly go through it so that you understand what's going on. First off, the class is decorated with an attribute that defines the subject under test. In this example, this is the TicTacToeGamePresenter. The subject is used when displaying the output of running the specs, which you will learn about later.

The Establish delegate, context, sets up the necessary classes and dependencies, and puts the system in a known state. This can be compared to Given in the template you used for the SpecFlow scenarios.

The Because delegate, of, performs the action on the system under test. Notice that the TicTacToeGamePresenter instance is named SUT, which stands for System Under Test. This again helps to focus on whose behavior you are defining.

Finally, the two It delegates (otherwise known as behaviors) perform the assertions that have taken place because of the action.

In this specification, you are providing a stub instance of a GameView and using Rhino Mocks to automatically generate it. Your expectations are that the presenter will write some lines to the view (the welcome message) and will prompt the view for the coordinates for the next move.

At the moment, however, the code will not compile, because neither the write_line or get_coordinates_for_next_move methods exist.

To stop the IDE from complaining, update the GameView interface to include the two new methods.

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public interface GameView

{

void write_line(string message);

void get_coordinates_for_next_move();

}

}

Code file [GameView.cs] available for download at Wrox.com.

note

To keep this chapter at a manageable size, and to communicate the concepts of BDD to you as succinctly as possible, I have jumped over an important step that I perform when designing a system behavior first. Typically, I will create all production code in the same class as the specification until such time as I am happy with my interface and class designs. The benefits of this are that I am able to work easily within one class that I don't consider to be production code. This important separation enables me to spike different design solutions easier than if I had my code spread out across a number of class projects, plus, subconsciously, I don't feel so precious about the code. So, I am more likely to try a number of designs until I am happy.

Again, remember that you defined these methods from the point of view of the user. You may not have realized it, but you have made a big design decision at this stage by asking for coordinates. You could have just as easily asked for a square number. Coordinates feel right at this stage, however, so let's stick with it.

With the GameView interface updated, you must also update the FakeGameView class.

note

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

private StringBuilder _display = new StringBuilder();

public string display()

{

return _display.ToString();

}

public FakeGameView()

{

_presenter =

new TicTacToeGamePresenter(this);

_presenter.start();

}

public void write_line(string message)

{

_display.AppendLine(message);

}

public void get_coordinates_for_next_move()

{

}

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

The get_coordinates_for_next_move method can remain empty. However, the write_line method will append each line to the display StringBuilder instance in order for you to be able to inspect within the step definition.

The class within the Specs.Core will now compile. But if you run the spec, it will fail because the TicTacToePresenter is not performing the expected behavior (that is, writing to the view and asking it to make a move).

Drop into the TicTacToeGamePresenter and update it with the following code:

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

private readonly GameView _game_view;

public TicTacToeGamePresenter(GameView game_view)

{

_game_view = game_view;

}

public void start()

{

_game_view.write_line("=========================");

_game_view.write_line("Lets Play Tic-Tac-Toe!!!!");

_game_view.write_line("=========================");

_game_view.write_line("When prompted please input the");

_game_view.write_line("coordinates of your move in the");

_game_view.write_line("format row,col e.g. 0,1 for the");

_game_view.write_line("first row and the second column");

_game_view.write_line("");

prompt_for_next_move();

}

private void prompt_for_next_move()

{

_game_view.write_line("X, make your move.");

_game_view.write_line("");

_game_view.get_coordinates_for_next_move();

}

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

Notice how you have hard-coded the string X, make your move. You know that X will not be the only player allowed to move. However, you just want to get the spec to pass in the simplest way possible before adding more complexity like tracking whose turn it is.

Build the solution and run the specs. You should see the output displayed as shown in Figure 14.16.

Figure 14.16 MSpec output showing the behaviors of the TicTacToeGamePresenter

14.16

Notice how the output reads like a set of requirements. Notice also how it matches your original expectations that you jotted down at the start of this section.

With no other behavior to add to the objects, jump back to the SpecFlow scenario in the Specs.UAT project and run the test. You should see that it passes, as shown in Figure 14.17.

Figure 14.17 SpecFlow output showing the passing of the “start a game” scenario

14.17

Great! Your first scenario is working. However, all you have to show is a passing specification, which is no good to your customer, who counts success in terms of working software. Let's integrate this into a real console application before you add any more behavior so that you can demonstrate the first scenario to your customer.

Integrating the Starting a Game Scenario

To run the game in a console application, you first need to create a real implementation of the GameView that will output the game display to a console, rather than appending to a StringBuilder.

Add a new class named ConsoleGameView to the root of the Ui.Console project and update it to match the following code:

note

using Wrox.BDD.Ui.Console.Presentation;

namespace Wrox.BDD.Ui.Console

{

public class ConsoleGameView : GameView

{

private TicTacToeGamePresenter _presenter;

public ConsoleGameView()

{

_presenter = new TicTacToeGamePresenter(this);

_presenter.start();

}

public void write_line(string message)

{

System.Console.WriteLine(message);

}

public void get_coordinates_for_next_move()

{

System.Console.ReadLine();

}

}

}

Code file [ConsoleGameView.cs] available for download at Wrox.com.

A ReadLine call within the get_coordinates_for_the_next_move method has been added to ensure that the display is shown until you press Enter.

Lastly, create an instance of the ConsoleGameView class within the main method of the Program class so that the game can be started.

note

namespace Wrox.BDD.Ui.Console

{

public class Program

{

static void Main(string[] args)

{

var game = new ConsoleGameView();

}

}

}

Code file [Program.cs] available for download at Wrox.com.

If you set the Ui.Console project as your startup project and press F5, you will see that a console application launches with welcome text, and a prompt for player X to make his move, as shown in Figure 14.18.

Figure 14.18 Console application showing the TicTacToe welcome message

14.18

Fantastic! You already have something you can show the customer!

Scenario: Alternating Players

The second scenario to define the behavior of playing a game refers to the alternating of a player after a move has been made. Add the scenario as shown in Figure 14.19 to the GamePlay.feature in the Spec.UAT project.

Figure 14.19 The SpecFlow feature file with the alternate players scenario

14.19

Because this scenario contains new steps, you can let SpecFlow auto-generate them for you by running the specs. Update the GamePlaySteps class with the new definitions and add the stub code, as shown here:

note

namespace Wrox.BDD.Specs.UAT.Steps

{

[Binding]

public class GamePlaySteps

{

[Given(@"I have read the introduction message")]

public void GivenIHaveReadTheIntroductionMessage()

{

var view = GameStorage.game_view;

view.clean_display();

}

[When(@"a player types in the coordinates ""(.*)""")]

public void WhenAPlayerTypesInTheCoordinates(string coordinates)

{

var game_presenter = GameStorage.presenter;

game_presenter.update_game_with_move(coordinates);

}

……

}

Code file [GamePlaySteps.cs] available for download at Wrox.com.

The first step is simply clearing the display of the view. This is only required during testing so that the scenarios can be kept to a manageable size, and so that you do not need to verify all of the text displayed on the view. The clean_display method will only be a method of the FakeGameView class, and will not be added to the interface, because this is only used in testing.

The second step receives the inputted coordinates from the user and passes them to the view. Again, note how you are defining the API of the presenter class from the view of its caller — in this case, it's the GameView.

You may have noticed that you now need to talk directly to the presenter, but currently you are not storing it in SpecFlow's context. To update this, amend the GameStorage class as shown in the following snippet:

note

using Wrox.BDD.Ui.Console.Presentation;

using TechTalk.SpecFlow;

namespace Wrox.BDD.Specs.UAT.StepHelpers

{

public static class GameStorage

{

public static TicTacToeGamePresenter presenter

{

get { return ScenarioContext.Current["Presenter"] as

TicTacToeGamePresenter; }

set { ScenarioContext.Current["Presenter"] = value; }

}

public static FakeGameView game_view

{

get { return ScenarioContext.Current["View"] as FakeGameView; }

set { ScenarioContext.Current["View"] = value; }

}

}

}

Code file [GameStorage.cs] available for download at Wrox.com.

You will need to store the presenter from within FakeGameView, as shown in the following snippet:

note

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

……

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this,

new TicTacToe());

GameStorage.presenter = _presenter;

_presenter.start();

}

……

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

While you have the FakeGameView class open, add the clean_display method as well.

note

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

……

public void clean_display()

{

_display.Clear();

}

……

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

Also, add the update_game_with_move method, but leave its body empty. Remember, you are only trying to get the code to a state where it complies and gives you a logic error.

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

……

public void update_game_with_move(string move_coordinates)

{

}

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

With the IDE happy, you can now build your solution and watch the scenario unsurprisingly fail. With nothing more to do at the step-definition level, let's drop into the behavior of the presenter and the Specs.Core project.

So, how will you achieve the behavior described by the scenario? Let's write down some expectations for the behavior of the presenter to help drive the object design. The presenter should do the following:

1. Ask the game for the next player to move.

2. Tell the game to place the current players token on a given square.

3. Display the game.

4. Display the next player to move.

Note how you are now talking about a game instance. This is where you start thinking in terms of the domain of the game and its responsibilities. You are rightly expecting a game to manage the current player, and to handle moves from the presenter.

Behavior 1: Ask for the Next Player

Let's begin by modifying the when_starting_a_new_game spec to add an additional behavior that expects the presenter to ask the game for the current player.

note

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(TicTacToeGamePresenter))]

public class when_starting_a_new_game

{

Establish context = () =>

{

game_view = MockRepository.GenerateStub<GameView>();

game = MockRepository.GenerateStub<Game>();

SUT = new TicTacToeGamePresenter(game_view, game);

};

private Because of = () =>

{

SUT.start();

};

……

private It should_ask_the_game_for_the_next_player_to_move = () =>

{

game.AssertWasCalled(x => x.current_token());

};

private static TicTacToeGamePresenter SUT;

private static Game game;

private static GameView game_view;

}

}

Code file [when_starting_a_new_game.cs] available for download at Wrox.com.

You have now introduced the concept of a Game. The Game interface will live in the Domain project, so ensure that you add a project reference to this from the Specs.Core project. The Game is responsible for the state and the logic governing the Tic-Tac-Toe game. The presenter, on the other hand, is responsible only for the presentation of the game, and handling user input.

With its single method, the Game interface should be added to the Domain project, as shown in the following code:

note

namespace Wrox.BDD.Domain

{

public interface Game

{

Token current_token();

}

}

Code file [Game.cs] available for download at Wrox.com.

The game returns a Token to represent the current player's token. Add the code to represent the Token to the Domain project, as shown in the following code:

note

using System;

namespace Wrox.BDD.Domain

{

public static class Tokens

{

public static Token x_token { get { return new Token("X"); } }

public static Token o_token { get { return new Token("O"); } }

}

public class Token : IEquatable<Token>

{

public string value { get; set;}

public Token(string value)

{

this.value = value;

}

public bool Equals(Token other)

{

return this.value == other.value;

}

public override string ToString()

{

return value;

}

}

}

Code file [Token.cs] available for download at Wrox.com.

The Token is what is known as a value object. You have overridden the equality method because two value objects should be equal if their values are equal.

You could have used a simple enumeration to portray the concept of the X and O tokens in the game of Tic-Tac-Toe. However, by using smart enumerations in the form of immutable value objects, you can easily add behavior at a later date.

You will now need to modify the TicTacToeGamePresenter constructor to expect an instance of the Game as defined in the spec. Update the presenter as shown in the following code and ensure that you add a reference to the Domain project:

note

using Wrox.BDD.Domain;

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

private readonly GameView _game_view;

private readonly Game _game;

public TicTacToeGamePresenter(GameView game_view, Game game)

{

_game_view = game_view;

_game = game;

}

……

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

You now have a bit of a problem. The presenter requires an instance of the Game in order to work. In specs, you can create stub instances using Rhino Mocks. However, you have already started to integrate the code, and also your FakeGameView requires a valid instance.

Update the FakeGameView and the ConsoleGameView, shown here, to include the as-yet-nonexistent TicTacToe implementation of the Game interface. Again, add a reference to the Domain project to the Specs.UAT project.

note

using Wrox.BDD.Ui.Console.Presentation;

using Wrox.BDD.Specs.UAT.StepHelpers;

using Wrox.BDD.Domain;

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

private StringBuilder _display = new StringBuilder();

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this, new TicTacToe());

GameStorage.presenter = _presenter;

_presenter.start();

}

……

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

namespace Wrox.BDD.Ui.Console

{

public class ConsoleGameView : GameView

{

private TicTacToeGamePresenter _presenter;

public ConsoleGameView()

{

_presenter =

new TicTacToeGamePresenter(this,new TicTacToe());

_presenter.start();

}

……

}

}

Code file [ConsoleGameView.cs] available for download at Wrox.com.

You can now create the TicTacToe class within the Domain project. For the time being, just hard-code it to return an X token. You will update this when you have written a spec to define its behavior.

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

public Token current_token()

{

return Tokens.x_token;

}

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

With the IDE happy, you now need to turn your attention to actually getting the spec to pass. Update the TicTacToePresenter so that it uses the Game instance to determine whose move it is.

note

using Wrox.BDD.Domain;

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

private readonly GameView _game_view;

private readonly Game _game;

public TicTacToeGamePresenter(GameView game_view, Game game)

{

_game_view = game_view;

_game = game;

}

……

private void prompt_for_next_move()

{

_game_view.write_line(String.Format(

"{0}, make your move.", _game.current_token()));

_game_view.write_line("");

_game_view.get_coordinates_for_next_move();

}

……

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

With the behavior added, run all the specs. You will find that the spec you were working on now passes, as shown in Figure 14.20.

Figure 14.20 The MSpec output showing the behaviors of the TiacTacToeGamePresenter

14.20

Behavior 2: Place the Token

For the next behavior criteria, you will need to create a new specification class that uses the TicTacToePresenter as its subject. Because you don't want to duplicate all of the setup code, you can refactor and move it all to a base class.

Add a new abstract class named with_a_presenter and move over all of the setup code from the context delegate of the when_starting_a_new_game class into the constructor so that both classes match the code shown here:

note

using Rhino.Mocks;

using Wrox.BDD.Ui.Console.Presentation;

using Wrox.BDD.Domain;

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

public abstract class with_a_presenter

{

public with_a_presenter()

{

game_view = MockRepository.GenerateStub<GameView>();

game = MockRepository.GenerateStub<Game>();

SUT = new TicTacToeGamePresenter(game_view, game);

}

protected static TicTacToeGamePresenter SUT;

protected static Game game;

protected static GameView game_view;

}

}

Code file [with_a_presenter.cs] available for download at Wrox.com.

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(TicTacToeGamePresenter))]

public class when_starting_a_new_game : with_a_presenter

{

Establish context = () =>

{

};

……

//protected static TicTacToeGamePresenter SUT;

//protected static Game game;

//protected static GameView game_view;

}

}

Code file [when_starting_a_new_game.cs] available for download at Wrox.com.

You can now create a new spec class that inherits from the with_a_presenter base class, as shown in the following definition that defines behavior number two as shown in your list:

note

using Machine.Specifications;

using Rhino.Mocks;

using Wrox.BDD.Ui.Console.Presentation;

using Wrox.BDD.Domain;

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(TicTacToeGamePresenter))]

public class when_a_player_places_a_token : with_a_presenter

{

Establish context = () =>

{

coordinate_text = "1,1";

coordinate = Coordinate.parse(coordinate_text);

};

private Because of = () =>

{

SUT.start();

SUT.update_game_with_move(coordinate_text);

};

private It should_tell_the_game_to_place_a_token = () =>

{

game.AssertWasCalled(x => x.place_token_for_current_player_at(

Arg<Coordinate>.Matches(c =>

c.Equals(coordinate))));

};

private static Coordinate coordinate;

private static string coordinate_text;

}

}

Code file [when_a_player_places_a_token.cs] available for download at Wrox.com.

The spec expects that the presenter will take input from the view, convert it to a coordinate, and then pass it to the game. In this spec, you have introduced the notation of a coordinate object to represent a location on the game grid.

Like Token, the Coordinate class is an immutable value object. Add it to the Domain project by matching the following code definition:

note

namespace Wrox.BDD.Domain

{

public class Coordinate : IEquatable<Coordinate>

{

public Coordinate(int x, int y)

{

X = x;

Y = y;

}

public int X { get; private set; }

public int Y { get; private set; }

public bool Equals(Coordinate other)

{

return this.X == other.X && this.Y == other.Y;

}

public override string ToString()

{

return string.Format("{0},{1}", X, Y);

}

public static Coordinate parse(string move_coordinates)

{

var coordinates = move_coordinates.Split(',');

return new Coordinate(int.Parse(coordinates[0].ToString()),

int.Parse(coordinates[1].ToString()));

}

}

}

Code file [Coordinate.cs] available for download at Wrox.com.

You didn't have to create a class to represent a coordinate. You could have simply passed two integers around, and had a helper method convert strings into integers. However, by creating a value object, you are representing an important concept in the domain. This will make it easy for other developers to understand the code, and easy for you when you must work on the codebase at a later date.

note

As mentioned, a value object is a small, simple object that represents a concept or concern in a business domain. Typically, value objects have no identity and are immutable. The value objects that you have used up to now have represented a coordinate on the game board, and a game token. It's a good idea to use value objects in place of simple parameter types in order to better express the concepts of the problem domain. It's also easier to add behavior and validation to value objects when needed, rather than adding procedural or transcript code around simple types. Value objects can also help to clarify complex entities by moving behavior to single-responsibility value objects that better convey the concern. You can learn more about value objects by reading Domain-Driven Design: Tackling Complexity in the Heart of Software (Boston: Addison-Wesley Professional, 2003) by Eric Evans.

To get the IDE to compile, you must update the Game interface with the new place_token_for_current_player_at method, as shown in the following code snippet:

note

namespace Wrox.BDD.Domain

{

public interface Game

{

Token current_token();

void place_token_for_current_player_at(Coordinate coordinate);

}

}

Code file [Game.cs] available for download at Wrox.com.

And, in turn, you must update the TicTacToe implementation. Again, just leave it blank for the time being.

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

public Token current_token()

{

return Tokens.x_token;

}

public void place_token_for_current_player_at(Coordinate coordinate)

{

}

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

To get the spec to pass, you must add the expected behavior to the presenter.

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

……

public void update_game_with_move(string move_coordinates)

{

var coordinate = Coordinate.parse(move_coordinates);

_game.place_token_for_current_player_at(coordinate);

}

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

If you run the specs now, you will find that they pass! But you may have noticed that you added some behavior on the Coordinate class without a spec to verify it. This is fine to do as long as you remember to add a spec to verify behavior before you go on to specify another piece of behavior in the system.

To verify the behavior of the Coordinate class, add a new folder named Domain_Specs to store the spec related to coordinate, and add to it the following class listing:

note

using Machine.Specifications;

using Wrox.BDD.Domain;

using NUnit.Framework;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(Coordinate))]

public class when_parsing_a_valid_coordinate

{

private Because of = () =>

{

x_coordinate = "2";

y_coordinate = "1";

coordinate = Coordinate.parse(

String.Format("{0},{1}", x_coordinate, y_coordinate));

};

private It should_be_able_to_correctly_parse_the_coordinate = () =>

{

Assert.That(coordinate.X, Is.EqualTo(int.Parse(x_coordinate)));

Assert.That(coordinate.Y, Is.EqualTo(int.Parse(y_coordinate)));

};

private static Coordinate coordinate;

private static string x_coordinate;

private static string y_coordinate;

}

}

Code file [when_parsing_a_valid_coordinate.cs] available for download at Wrox.com.

Now you have two of the presenter steps taken care of and are ready to move on to number three.

Behavior 3: Display the Game

Behavior number three deals with the displaying of the game. Add a new behavior to the when_a_player_places_a_token specification class, as detailed here:

note

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(TicTacToeGamePresenter))]

public class when_a_player_places_a_token : with_a_presenter

{

Establish context = () =>

{

coordinate_text = "1,1";

coordinate = Coordinate.parse(coordinate_text);

};

private Because of = () =>

{

SUT.start();

SUT.update_game_with_move(coordinate_text);

};

……

private It should_render_the_game = () =>

{

board_renderer.AssertWasCalled(x => x.render(game));

};

private static Coordinate coordinate;

private static string coordinate_text;

}

}

Code file [when_a_player_places_a_token.cs] available for download at Wrox.com.

You have now been introduced to the concept of a board_renderer. The responsibility of this object is to render the state of a game instance.

Update the with_a_presenter base class to include the board_renderer as a dependency of the presenter.

note

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

public abstract class with_a_presenter

{

public with_a_presenter()

{

game = MockRepository.GenerateStub<Game>();

game_view = MockRepository.GenerateStub<GameView>();

board_renderer = MockRepository.GenerateStub<BoardRenderer>();

SUT = new TicTacToeGamePresenter(game_view, game, board_renderer);

}

protected static TicTacToeGamePresenter SUT;

protected static Game game;

protected static GameView game_view;

protected static BoardRenderer board_renderer;

}

}

Code file [with_a_presenter.cs] available for download at Wrox.com.

The interface for the BoardRenderer is very simple, and contains a single method that returns a string.

note

using Wrox.BDD.Domain;

namespace Wrox.BDD.Ui.Console.Presentation

{

public interface BoardRenderer

{

string render(Game game);

}

}

Code file [BoardRenderer.cs] available for download at Wrox.com.

To match the expected behavior, you must update the TicTacToeGamePresenter to accept a BoardRenderer as a constructor argument, and ensure that it calls its render method passing the instance of the game.

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

private readonly GameView _game_view;

private readonly Game _game;

private readonly BoardRenderer _board_renderer;

public TicTacToeGamePresenter(GameView game_view, Game game,

BoardRenderer board_renderer)

{

_game_view = game_view;

_game = game;

_board_renderer = board_renderer;

}

……

public void update_game_with_move(string move_coordinates)

{

var coordinate = Coordinate.parse(move_coordinates);

_game.place_token_for_current_player_at(coordinate);

display_game();

prompt_for_next_move();

}

private void display_game()

{

_game_view.write(_board_renderer.render(_game));

_game_view.write_line("");

}

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

You have introduced a new write method on the view, which simply writes text straight to the console without adding a line. This extra write method is required because the view of the game will not be able to be represented on a single line. Update the GameView interface as shown in the following code snippet:

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public interface GameView

{

void write_line(string message);

void write(string message);

void get_coordinates_for_next_move();

}

}

Code file [GameView.cs] available for download at Wrox.com.

In order for the code to compile, you must supply a concrete instance of the BoardRenderer for use within the FakeGameView and the ConsoleGameView.

Add a new class called PlainTextGameBoardRenderer to the Presentation folder of the Ui.Console project. Remember, this is a presentation concern, and that's why you are adding this to the presentation layer of your application.

note

using Wrox.BDD.Domain;

namespace Wrox.BDD.Ui.Console.Presentation

{

public class PlainTextGameBoardRenderer : BoardRenderer

{

public string render(Game game)

{

var squares = new string[3,3];

squares[2, 2] = "X";

var grid_display = new StringBuilder();

var row_seperator = "";

for (int row = 0; row <= 2; row++)

{

if (!String.IsNullOrEmpty(row_seperator))

grid_display.AppendLine(row_seperator);

var pipe = "";

var row_display = new StringBuilder();

for (int column = 0; column <= 2; column++)

{

row_display.Append(string.Format("{0} {1} ", pipe,

pad_if_square_empty(squares[row, column])));

pipe = "|";

}

grid_display.AppendLine(row_display.ToString());

row_seperator = "-----------";

}

return grid_display.ToString();

}

private string pad_if_square_empty(string value)

{

return String.IsNullOrEmpty(value) ? " " : value;

}

}

}

Code file [PlainTextGameBoardRenderer.cs] available for download at Wrox.com.

There is a fair bit going on in this class. From a 1,000-foot view, it simply generates a string representation of a 3 × 3 grid using a string multi-array to define where the tokens are on that grid. You should note that the scenario expects an X token to be displayed at position 2,2. You have hard-coded this in the PlainTextGameBoardRenderer class because you have no method of asking the Game instance where the tokens are. This will obviously be altered in upcoming specs, but for now, you just want to get the scenario passing.

With an instance of the BoardRenderer in place, you can update the FakeGameView and ConsoleGameView to instantiate an instance of the PlainTextGameBoardRenderer and pass it in as an argument to the presenter, as well as include the implementation for the new write method.

note

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

private StringBuilder _display = new StringBuilder();

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this, new TicTacToe(),

new PlainTextGameBoardRenderer());

GameStorage.presenter = _presenter;

_presenter.start();

}

……

public void write(string message)

{

_display.Append(message);

}

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

namespace Wrox.BDD.Ui.Console

{

public class ConsoleGameView : GameView

{

private TicTacToeGamePresenter _presenter;

public ConsoleGameView()

{

_presenter =

new TicTacToeGamePresenter(this, new TicTacToe(),

new PlainTextGameBoardRenderer());

_presenter.start();

}

public void write_line(string message)

{

System.Console.WriteLine(message);

}

public void get_coordinates_for_next_move()

{

System.Console.ReadLine();

}

public void write(string message)

{

System.Console.Write(message);

}

}

}

Code file [ConsoleGameView.cs] available for download at Wrox.com.

Build and run your specs, and they should all pass. That's another one crossed off the list.

Now, check to see how far you are with the scenario. Cool, it's displaying the grid, but the scenario still fails because of the missing line prompting the next player to make a move — which is number four on the list. Let's deal with that now.

Behavior 4: Display the Next Player

The behavior of supplying the next player to move is the responsibility of the Game. At the moment, it's hard-coded in the TicTacToe instance to always return token X. Because the TicTacToe class is the subject of your spec, and because you are likely to have more behaviors to verify against it, let's create an abstract base class for use with the specifications.

note

using Wrox.BDD.Domain;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

public abstract class with_a_tictactoe_game

{

public with_a_tictactoe_game()

{

SUT = new TicTacToe();

}

protected static Game SUT;

}

}

Code file [with_a_tictactoe_game.cs] available for download at Wrox.com.

With the base class in place, create a new specification class, again in the Domain_Specs folder of the Spec.Core project.

note

using Machine.Specifications;

using Rhino.Mocks;

using Wrox.BDD.Domain;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(TicTacToe))]

public class when_placing_a_token_on_the_board : with_a_tictactoe_game

{

Establish context = () =>

{

coordinate_text = "1,1";

coordinate = Coordinate.parse(coordinate_text);

};

private Because of = () =>

{

SUT.place_token_for_current_player_at(coordinate);

};

private It should_alternate_the_player = () =>

{

player_tracker.AssertWasCalled(x => x.finish_players_move());

};

private static Coordinate coordinate;

private static string coordinate_text;

}

}

Code file [when_placing_a_token_on_the_board.cs] available for download at Wrox.com.

Your specification expects that a call should be made to a player_tracker instance after a move has been made. The responsibilities of player_tracker are to simply remember whose turn it is, and to alternate after the finish_players_move method is called. Remember, this code doesn't exist. You are simply thinking about the most logical and straightforward way of determining whose turn it is.

It makes sense that this player_tracker is a dependency of the Game. Update the with_a_tictactoe_game base class to include the new constructor dependency, as shown in the following code:

note

using Wrox.BDD.Domain;

using Rhino.Mocks;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

public abstract class with_a_tictactoe_game

{

public with_a_tictactoe_game()

{

player_tracker = MockRepository.GenerateStub<PlayerTracker>();

SUT = new TicTacToe(player_tracker);

}

protected static Game SUT;

protected static PlayerTracker player_tracker;

}

}

Code file [with_a_tictactoe_game.cs] available for download at Wrox.com.

Now you must create the new interface within the Domain project, as shown here:

note

namespace Wrox.BDD.Domain

{

public interface PlayerTracker

{

Token current_player();

void finish_players_move();

}

}

Code file [PlayerTracker.cs] available for download at Wrox.com.

Notice that the current_player method has been added. You have not previously specified this behavior. However, experience has shown that this should be the responsibility of the PlayerTracker and not the Game.

Modify the TicTacToe class to accept an instance of the PlayerTracker via its constructor. Replace the hard-coded token X in the current_token method with a delegation to the PlayerTracker. Finally, add a call to the PlayerTracker to finish the player's move after a token has been placed. This is all shown in the following code:

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

private PlayerTracker _player_tracker;

public TicTacToe(PlayerTracker player_tracker)

{

_player_tracker = player_tracker;

}

public Token current_token()

{

return _player_tracker.current_player();

}

public void place_token_for_current_player_at(Coordinate coordinate)

{

_player_tracker.finish_players_move();

}

……

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

You must now create an instance of the PlayerTracker to supply to the FakeGameView and ConsoleGameView. Add a new TokenTracker class with the following definition:

note

namespace Wrox.BDD.Domain

{

public class TokenTracker : PlayerTracker

{

private Token _current_playing_token = Tokens.x_token;

public Token current_player()

{

return _current_playing_token;

}

public void finish_players_move()

{

_current_playing_token =

(_current_playing_token.Equals(Tokens.x_token))

? Tokens.o_token :

Tokens.x_token;

}

}

}

Code file [TokenTracker.cs] available for download at Wrox.com.

TokenTracker simply stores a single token and, starting with token X, alternates it when a call to finish_players_move is made.

You can now update the FakeGameView and the ConsoleGameView.

note

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

private StringBuilder _display = new StringBuilder();

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this,

new TicTacToe(new TokenTracker()),

new PlainTextGameBoardRenderer());

GameStorage.presenter = _presenter;

_presenter.start();

}

……

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

namespace Wrox.BDD.Ui.Console

{

public class ConsoleGameView : GameView

{

private TicTacToeGamePresenter _presenter;

public ConsoleGameView()

{

_presenter =

new TicTacToeGamePresenter(this, new TicTacToe(new

TokenTracker()),

new PlainTextGameBoardRenderer());

_presenter.start();

}

……

}

}

Code file [ConsoleGameView.cs] available for download at Wrox.com.

Build and run all of your specs. All passing? Great. That was the last expected piece of behavior. Now, if you run your scenarios, you should see them all passing, as shown in Figure 14.21.

Figure 14.21 The SpecFlow output showing the passing of the alternate player scenario

14.21

With the code all working under testing, let's integrate it and see if it works for real.

Integrating the Alternate a Player Scenario

The only modification you need to make to get the code integrated is to wire up the input, as shown in the following code:

note

namespace Wrox.BDD.Ui.Console

{

public class ConsoleGameView : GameView

{

……

public void get_coordinates_for_next_move()

{

var coordinates = System.Console.ReadLine();

_presenter.update_game_with_move(coordinates);

}

……

}

}

Code file [ConsoleGameView.cs] available for download at Wrox.com.

You should now be able to run the code and input a coordinate as shown in Figure 14.22. Remember to input it using the valid syntax because you have not added code for the non-happy-day scenarios. Also, note that whatever coordinate you input, the screen will always display an X token at grid reference 2,2. Hmmm, that's not great, but the system is coming along.

Figure 14.22 The Console application showing the game welcome message and prompt for player O to move

14.22

The next scenario to tackle is displaying the game after a series of moves. This should help to display a true representation of the moves that the player has made.

Scenario: Displaying the Game

Figure 14.23 shows the scenario for displaying a game after a series of moves. This scenario should be added to the GamePlay.feature file.

Figure 14.23 The GamePlay feature showing the scenario for displaying the game

14.23

With the new steps that play a series of moves, a new step definition must be created. Add the following code to the GamePlaySteps class:

note

namespace Wrox.BDD.Specs.UAT.Steps

{

[Binding]

public class GamePlaySteps

{

……

[Given(@"the following moves are played:")]

public void GivenTheFollowingMovesArePlayed(Table table)

{

foreach (var row in table.Rows)

{

GameStorage.presenter.update_game_with_move(

string.Format("{0},{1}", row["row"], row["column"]));

}

GameStorage.game_view.clean_display();

}

}

}

Code file [GamePlaySteps.cs] available for download at Wrox.com.

To support the display of the game, you must dive into the behavior of the objects that support the application in terms of rendering a game and handling the placement of tokens. Let's make a list of the behaviors you must add:

1. The Game should place the token on a square on the grid.

2. The Game should be able to confirm placement of token.

3. The Game rendered should be able to obtain a read-only view of the grid for rendering.

Behavior 1: Placing the Token on the Grid

Update the when_placing_a_token_on_the_board spec to match the following code:

note

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(TicTacToe))]

public class when_placing_a_token_on_the_board : with_a_tictactoe_game

{

Establish context = () =>

{

coordinate_text = "1,1";

coordinate = Coordinate.parse(coordinate_text);

player_tracker.Stub(x => x.current_player()).Return(Tokens.x_token);

};

private Because of = () =>

{

SUT.place_token_for_current_player_at(coordinate);

};

private It should_place_a_token_on_the_grid = () =>

{

tic_tac_toe_grid.AssertWasCalled(x => x.place_token_at(

Arg<Coordinate>.Matches(c => c.Equals(coordinate)),

Arg<Token>.Matches(c => c.Equals(Tokens.x_token))));

};

……

private static Coordinate coordinate;

private static string coordinate_text;

}

}

Code file [when_placing_a_token_on_the_board.cs] available for download at Wrox.com.

Notice that you must mock the behavior of the player_tracker in the context delegate so that it will correctly return token X as the current player.

The new behavior defines that the TicTacToe game should pass the coordinate onto a tic_tac_toe_grid, along with the current playing token.

The tic_tac_toe_grid will represent the underlying board grid that the game is based upon. The grid is essential to the game, and, thus, should be a dependency of the game supplied at construction. Amend the with_a_tictactoe_game base class to add the new grid as a parameter to the construction of theTicTacToe instance, as shown here:

note

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

public abstract class with_a_tictactoe_game

{

public with_a_tictactoe_game()

{

player_tracker = MockRepository.GenerateStub<PlayerTracker>();

tic_tac_toe_grid = MockRepository.GenerateStub<Grid>();

SUT = new TicTacToe(player_tracker, tic_tac_toe_grid);

}

protected static Game SUT;

protected static PlayerTracker player_tracker;

protected static Grid tic_tac_toe_grid;

}

}

Code file [with_a_tictactoe_game.cs] available for download at Wrox.com.

It's important to keep the grid and the game separate to support the single responsibility principle, and to reinforce domain concepts. The grid looks after everything to do with the playing board (for example, placing tokens and knowing what tokens are where). The game class knows (or at least knows who to talk to) about implementing the rules of the game of Tic-Tac-Toe, such as whose turn is next, and if the game is in a winning or drawn state.

Create the Grid interface in the Domain project with its single method.

note

namespace Wrox.BDD.Domain

{

public interface Grid

{

void place_token_at(Coordinate coordinate, Token token);

}

}

Code file [Grid.cs] available for download at Wrox.com.

Now, update the TicTacToe class by adding the Grid to its constructor, and by implementing the expected behavior.

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

private PlayerTracker _player_tracker;

private Grid _grid;

public TicTacToe(PlayerTracker player_tracker, Grid grid)

{

_player_tracker = player_tracker;

_grid = grid;

}

public Token current_token()

{

return _player_tracker.current_player();

}

public void place_token_for_current_player_at(Coordinate coordinate)

{

_grid.place_token_at(coordinate, current_token());

_player_tracker.finish_players_move();

}

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

To run the specs, you must create an instance of the Grid in order to supply to both the FakeGameView and ConsoleGameViews. For the time being, the grid instance will contain no behavior. Add a new class named NineSquareGrid to the Domain project that implements the Grid interface.

note

namespace Wrox.BDD.Domain

{

public class NineSquareGrid : Grid

{

public void place_token_at(Coordinate coordinate, Token token)

{

}

}

}

Code file [NineSquareGrid.cs] available for download at Wrox.com.

You can now update the FakeGameView and ConsoleGameView with the new constructor dependency.

note

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

private StringBuilder _display = new StringBuilder();

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this,

new TicTacToe(new TokenTracker(),

new NineSquareGrid()),

new PlainTextGameBoardRenderer());

GameStorage.presenter = _presenter;

_presenter.start();

}

……

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

namespace Wrox.BDD.Ui.Console

{

public class ConsoleGameView : GameView

{

private TicTacToeGamePresenter _presenter;

public ConsoleGameView()

{

_presenter =

new TicTacToeGamePresenter(this,

new TicTacToe(new TokenTracker(),

new NineSquareGrid()),

new PlainTextGameBoardRenderer());

_presenter.start();

}

……

}

}

Code file [ConsoleGameView.cs] available for download at Wrox.com.

You will now be able to compile your code and then test the specs. Great! You have another passing specification.

Behavior 2: Confirming Placement of a Token

Okay, now you must create some specifications with the Grid as the subject. Add a new class named when_checking_for_a_token_on_the_grid and update it with the following code:

note

using Machine.Specifications;

using Wrox.BDD.Domain;

using NUnit.Framework;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(NineSquareGrid))]

public class when_checking_for_a_token_on_the_grid

{

Establish context = () =>

{

coordinate_with_token = Coordinate.parse("1,1");

coordinate_without_token = Coordinate.parse("2,2");

SUT = new NineSquareGrid();

};

private Because of = () =>

{

SUT.place_token_at(coordinate_with_token, Tokens.x_token);

};

private It should_contain_a_token = () =>

{

Assert.That(SUT.contains_token_at(coordinate_with_token), Is.True);

};

private It should_not_contain_a_token = () =>

{

Assert.That(SUT.contains_token_at(coordinate_without_token), Is.False);

};

private static NineSquareGrid SUT;

private static Coordinate coordinate_with_token;

private static Coordinate coordinate_without_token;

}

}

Code file [when_checking_for_a_token_on_the_grid.cs] available for download at Wrox.com.

This specification defines that a grid should be able to retain the placement of a token. To start to add the behavior, first amend the Grid interface to match the following code:

note

namespace Wrox.BDD.Domain

{

public interface Grid

{

void place_token_at(Coordinate coordinate, Token token);

bool contains_token_at(Coordinate coordinate);

}

}

Code file [Grid.cs] available for download at Wrox.com.

Next, implement the new method in the NineSqureGrid implementation of the interface.

note

namespace Wrox.BDD.Domain

{

public class NineSquareGrid : Grid

{

public void place_token_at(Coordinate coordinate, Token token)

{

}

public bool contains_token_at(Coordinate coordinate)

{

return true;

}

}

}

Code file [NineSquareGrid.cs] available for download at Wrox.com.

If you run the specs now, only one will pass. This is because you have hard-coded the contains_token_at to always return true. Let's update the NineSquareGrid to match the expected behavior.

note

namespace Wrox.BDD.Domain

{

public class NineSquareGrid : Grid

{

protected readonly Token[,] _squares;

public NineSquareGrid()

{

_squares = new Token[3, 3];

}

public void place_token_at(Coordinate coordinate, Token token)

{

_squares[coordinate.X, coordinate.Y] = token;

}

public bool contains_token_at(Coordinate coordinate)

{

return _squares[coordinate.X, coordinate.Y] != null;

}

}

}

Code file [NineSquareGrid.cs] available for download at Wrox.com.

You have elected to store tokens in a multiple array. Notice again that you aren't bothering to check if the coordinate is within the boundaries of the array. You will add this to the running list of edge cases to deal with after you have the happy-day scenarios passing.

Run the specs and all should now be passing. You are making some good progress now!

Behavior 3: Obtaining a Read-only View for Rendering

The final piece of behavior on the list is for the BoardRenderer to obtain a view of the game grid for rendering. You want the game to only expose a read-only view of the grid, because you are allowing access from the presentation layer, and you don't want the presentation code to bypass any logic and muddle with the data. With this in mind, create a specification with the PlainTextGameBoardRenderer as the subject named when_rendering_the_game, as shown in the following code:

note

using Machine.Specifications;

using Wrox.BDD.Domain;

using Wrox.BDD.Ui.Console.Presentation;

using Rhino.Mocks;

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(PlainTextGameBoardRenderer))]

public class when_rendering_the_game

{

Establish context = () =>

{

var square_array = new string[3, 3];

game = MockRepository.GenerateStub<Game>();

game.Stub(x => x.get_game_view())

.Return(new GridView() { squares = square_array });

SUT = new PlainTextGameBoardRenderer();

};

private Because of = () =>

{

SUT.render(game);

};

private It should_ask_the_game_for_a_readonly_view = () =>

{

game.AssertWasCalled(x => x.get_game_view());

};

private static PlainTextGameBoardRenderer SUT;

private static Game game;

}

}

Code file [when_rendering_the_game.cs] available for download at Wrox.com.

You will now need to update the Game interface and add the new method call that will return the yet undefined GridView class.

note

namespace Wrox.BDD.Domain

{

public interface Game

{

Token current_token();

void place_token_for_current_player_at(Coordinate coordinate);

GridView get_game_view();

}

}

Code file [Game.cs] available for download at Wrox.com.

Next, create the GridView class itself.

note

namespace Wrox.BDD.Domain

{

public class GridView

{

public string[,] squares { get; set; }

}

}

Code file [GridView.cs] available for download at Wrox.com.

You could have just as easily returned a multi-string array, but wrapping it in the GridView class helps to convey the concept of a view of the grid in a clearer way.

With the addition to the Game interface, you will now, of course, need to update the TicTacToe instance to implement the new method. Simply have it return a new instance of the GridView populated with an empty multi-dimensioned string array, as shown in the following code:

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

……

public GridView get_game_view()

{

return new GridView(){ squares = new string[3,3]};

}

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

To meet the expected behavior, you must ensure that a call is made to obtain the GridView during the render method of the PlainTextGameBoardRenderer class.

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public class PlainTextGameBoardRenderer : BoardRenderer

{

public string render(Game game)

{

var squares = game.get_game_view().squares;

var grid_display = new StringBuilder();

var row_seperator = "";

for (int row = 0; row <= 2; row++)

{

if (!String.IsNullOrEmpty(row_seperator))

grid_display.AppendLine(row_seperator);

var pipe = "";

var row_display = new StringBuilder();

for (int column = 0; column <= 2; column++)

{

row_display.Append(string.Format("{0} {1} ", pipe,

pad_if_square_empty(squares[row, column])));

pipe = "|";

}

grid_display.AppendLine(row_display.ToString());

row_seperator = "-----------";

}

return grid_display.ToString();

}

private string pad_if_square_empty(string value)

{

return String.IsNullOrEmpty(value) ? " " : value;

}

}

}

Code file [PlainTextGameBoardRenderer.cs] available for download at Wrox.com.

You should now be about to build your code and run your specs. However, the responsibility of creating a read-only view of the grid should not rest with the game, but instead the grid instance should be able to produce a read-only view of itself. Let's create another spec with the NineSquareGrid as the subject and add this behavior.

note

using Machine.Specifications;

using Wrox.BDD.Domain;

using NUnit.Framework;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(NineSquareGrid))]

public class when_generating_a_readonly_view_for_rendering

{

Establish context = () =>

{

coordinate_with_X_token = Coordinate.parse("1,1");

coordinate_with_O_token = Coordinate.parse("2,2");

SUT = new NineSquareGrid();

};

private Because of = () =>

{

SUT.place_token_at(coordinate_with_X_token, Tokens.x_token);

SUT.place_token_at(coordinate_with_O_token, Tokens.o_token);

result = SUT.generate_grid_view();

};

private It should_have_the_X_token_in_the_correct_position = () =>

{

Assert.That(result.squares[coordinate_with_X_token.X,

coordinate_with_X_token.Y],

Is.EqualTo(Tokens.x_token.value));

};

private It should_have_the_O_token_in_the_correct_position = () =>

{

Assert.That(result.squares[coordinate_with_O_token.X,

coordinate_with_O_token.Y],

Is.EqualTo(Tokens.o_token.value));

};

private static GridView result;

private static NineSquareGrid SUT;

private static Coordinate coordinate_with_X_token;

private static Coordinate coordinate_with_O_token;

}

}

Code file [when_generating_a_readonly_view_for_rendering.cs] available for download at Wrox.com.

Now, add the new method to generate the grid view to the Grid interface.

note

namespace Wrox.BDD.Domain

{

public interface Grid

{

void place_token_at(Coordinate coordinate, Token token);

bool contains_token_at(Coordinate coordinate);

GridView generate_grid_view();

}

}

Code file [Grid.cs] available for download at Wrox.com.

Next, update the NineSquareGrid itself by adding the code that will build the read-only view.

note

namespace Wrox.BDD.Domain

{

public class NineSquareGrid : Grid

{

……

public GridView generate_grid_view()

{

var readonly_squares = new string[3,3];

for (int row = 0; row < 3; row++)

for (int column = 0; column < 3; column++)

readonly_squares[row, column] =

_squares[row, column] == null ?

"" : _squares[row, column].value;

return new GridView() {squares = readonly_squares};

}

}

}

Code file [NineSquareGrid.cs] available for download at Wrox.com.

With the responsibility now with the grid to produce the read-only view, you can update the TicTacToe class to delegate the view creation to the grid.

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

……

public GridView get_game_view()

{

return _grid.generate_grid_view();

}

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

Run your specs and all should pass. Now, with all the behavior added in the objects, your scenario should now pass, as shown in Figure 14.24.

Figure 14.24 SpecFlow output showing the passing of the scenario to display a game

14.24

Brilliant! You can now display the grid. Let's see what it looks like when you run the game for real.

Integrating the Displaying a Game Scenario

If you run the game, you see that whenever you make a move, the grid display is updated and the current player alternates. There is one problem, however. The game will go on forever because there is no check for a winning line!

Another issue found is that there is nothing to stop a player from placing a token on a square that is already occupied. You'd better add this to this list of behaviors to verify later on.

Scenario: Winning the Game with Three in a Row

In order for a game to finish, you must check for a winning condition. A win is three of the same token in a line. Add a new feature named PlayerWinsAGame.feature to the features folder of the Specs.UAT project, and update it to match the scenario in Figure 14.25.

Figure 14.25 The SpecFlow PlayerWinsAGame.feature with the diagonal win scenario

14.25

As luck would have it, you don't need to add any more step definitions because this scenario reuses all of your existing steps.

Let's jot down some initial steps that must occur for the view to display if a player has won.

1. The presenter should end the game if the current player is the winner.

2. Game should check for a winning line.

3. Presenter should display the winner to the view.

Behavior 1: End the Game if There Is a Winner

The first behavior on the list defines that in order for the presenter to display if a player has won the game, it must check with the game instance if the game has been won by the current player after each token placement. Add a new behavior definition to the when_a_player_places_a_token specification to verify that a check is made after a token is placed.

note

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(TicTacToeGamePresenter))]

public class when_a_player_places_a_token : with_a_presenter

{

……

private It should_check_if_the_current_player_has_won_the_game = () =>

{

game.AssertWasCalled(x => x.the_current_player_has_won_the_game());

};

}

}

Code file [when_a_player_places_a_token.cs] available for download at Wrox.com.

The specification defines that the presenter should call a method on the Game interface to determine if the game has been won. Add this to the Game interface, as shown in the following code:

note

namespace Wrox.BDD.Domain

{

public interface Game

{

Token current_token();

void place_token_for_current_player_at(Coordinate coordinate);

GridView get_game_view();

bool the_current_player_has_won_the_game();

}

}

Code file [Game.cs] available for download at Wrox.com.

With a change to the interface, there must also be a change to the TicTacToe class that implements it. For the moment, simply hard-code a false return.

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

……

public bool the_current_player_has_won_the_game()

{

return false;

}

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

In order to get the specification to pass, you must update the TicTacToeGamePresenter to match the expected behavior by checking with the game for a winner.

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

……

public void update_game_with_move(string move_coordinates)

{

var coordinate = Coordinate.parse(move_coordinates);

_game.place_token_for_current_player_at(coordinate);

display_game();

if (!_game.the_current_player_has_won_the_game())

prompt_for_next_move();

}

……

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

Run the specs and all should pass. Now, what's next on the list?

Behavior 2: Check for a Winning Line

To get the Game instance to check for a winning line, first create a new specification with the TicTacToe class as the subject.

note

using Machine.Specifications;

using Wrox.BDD.Domain;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(TicTacToe))]

public class when_checking_if_the_current_player_has_won_the_game :

with_a_tictactoe_game

{

private Because of = () =>

{

SUT.the_current_player_has_won_the_game();

};

private It should_tell_the_game_to_place_a_token = () =>

{

line_checker.AssertWasCalled(x =>

x.contains_a_winning_line(tic_tac_toe_grid));

};

}

}

Code file [when_checking_if_the_current_player_has_won_the_game.cs] available for download at Wrox.com.

You have now introduced the concept of a line_checker. This class will be responsible for determining if the grid contains three tokens in a row. Because you need this for the game to function correctly, add it as a constructor dependency and update the base specification class.

note

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

public abstract class with_a_tictactoe_game

{

public with_a_tictactoe_game()

{

player_tracker = MockRepository.GenerateStub<PlayerTracker>();

tic_tac_toe_grid = MockRepository.GenerateStub<Grid>();

line_checker = MockRepository.GenerateStub<LineChecker>();

SUT = new TicTacToe(player_tracker, tic_tac_toe_grid, line_checker);

}

protected static Game SUT;

protected static PlayerTracker player_tracker;

protected static Grid tic_tac_toe_grid;

protected static LineChecker line_checker;

}

}

Code file [with_a_tictactoe_game.cs] available for download at Wrox.com.

Create the new interface for the winning line checker.

note

namespace Wrox.BDD.Domain

{

public interface LineChecker

{

bool contains_a_winning_line(Grid tic_tac_toe_grid);

}

}

Code file [LineChecker.cs] available for download at Wrox.com.

As you probably noticed, the code won't compile, so update the TicTacToe class to accept an instance of the LineChecker and also delegate to the LineChecker the responsibility of checking if the current player has won.

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

private PlayerTracker _player_tracker;

private Grid _grid;

private readonly LineChecker _line_checker;

public TicTacToe(PlayerTracker player_tracker, Grid grid,

LineChecker line_checker)

{

_player_tracker = player_tracker;

_grid = grid;

_line_checker = line_checker;

}

……

public bool the_current_player_has_won_the_game()

{

return _line_checker.contains_a_winning_line(_grid);

}

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

In order for the code to compile, the FakeGameView and the ConsoleGameView must be supplied a concrete implementation of the LineChecker. Because you are only interested in the diagonal line, add a new class named DiagonalWinningLineChecker to implement the interface, hard-coded with a negative response.

note

namespace Wrox.BDD.Domain

{

public class DiagonalWinningLineChecker : LineChecker

{

public bool contains_a_winning_line(Grid tic_tac_toe_grid)

{

return false;

}

}

}

Code file [DiagonalWinningLineChecker.cs] available for download at Wrox.com.

Now, update the ConsoleGameView and the FakeGameView.

note

namespace Wrox.BDD.Ui.Console

{

public class ConsoleGameView : GameView

{

private TicTacToeGamePresenter _presenter;

public ConsoleGameView()

{

_presenter =

new TicTacToeGamePresenter(this,

new TicTacToe(new TokenTracker(), new NineSquareGrid(),

new DiagonalWinningLineChecker()),

new PlainTextGameBoardRenderer());

_presenter.start();

}

……

}

}

Code file [ConsoleGameView.cs] available for download at Wrox.com.

namespace Wrox.BDD.Specs.UAT

{

public class FakeGameView : GameView

{

private TicTacToeGamePresenter _presenter;

private StringBuilder _display = new StringBuilder();

public FakeGameView()

{

_presenter = new TicTacToeGamePresenter(this,

new TicTacToe(new TokenTracker(), new NineSquareGrid(),

new DiagonalWinningLineChecker()),

new PlainTextGameBoardRenderer());

GameStorage.presenter = _presenter;

_presenter.start();

}

……

}

}

Code file [FakeGameView.cs] available for download at Wrox.com.

Build and run your specs. They all pass!

You have now introduced some more behavior in the form of a new object, the LineChecker. You can add a fourth responsibility to your list that specifies that the job of the line checker is to determine if there is a winner, based on the state of the game grid.

Behavior 3: Displaying the Winner to the View

The next behavior on the list deals with the presenter announcing the winner by updating the view. Add a new spec with the TicTacToeGamePresenter as the subject, and add the following code to the class:

note

using Machine.Specifications;

using Wrox.BDD.Domain;

using Wrox.BDD.Ui.Console.Presentation;

using Rhino.Mocks;

namespace Wrox.BDD.Specs.Core.Presentation_Specs

{

[Subject(typeof(TicTacToeGamePresenter))]

public class when_a_player_gets_3_tokens_in_a_row : with_a_presenter

{

Establish context = () =>

{

coordinate_text = "1,1";

coordinate = Coordinate.parse(coordinate_text);

game.Stub(x => x.current_token()).Return(Tokens.x_token);

game.Stub(x => x.the_current_player_has_won_the_game()).Return(true);

};

private Because of = () =>

{

SUT.start();

SUT.update_game_with_move(coordinate_text);

};

private It should_announce_that_he_has_won_the_game = () =>

{

game_view.AssertWasCalled(x => x.write_line("X has won the game!"));

};

private static Coordinate coordinate;

private static string coordinate_text;

}

}

Code file [when_a_player_gets_3_tokens_in_a_row.cs] available for download at Wrox.com.

Because the presenter already has the Game as a dependency, all you must do is amend the TicTacToeGamePresenter to check for a winner, and then announce that the current player is the winner.

note

namespace Wrox.BDD.Ui.Console.Presentation

{

public class TicTacToeGamePresenter

{

……

public void update_game_with_move(string move_coordinates)

{

var coordinate = Coordinate.parse(move_coordinates);

_game.place_token_for_current_player_at(coordinate);

display_game();

if (_game.the_current_player_has_won_the_game())

announce_current_player_as_the_winner();

else

prompt_for_next_move();

}

private void announce_current_player_as_the_winner()

{

_game_view.write_line(string.Format("{0} has won the game!",

_game.current_token()));

}

……

}

}

Code file [TicTacToeGamePresenter.cs] available for download at Wrox.com.

If you run the specs after that small amendment, they should all pass!

Behavior 4: Check the Grid for a Winner

Now, let's move on to the last behavior for this scenario — adding the behavior to the DiagonalWinningLineChecker.

Before getting into the nitty-gritty of the DiagonalWinningLineChecker, let's think about how you want to communicate with the grid in order to ascertain whether there are three of the same token in a diagonal line.

The following code is some pseudo-code to visualize how you would like the DiagonalWinningLineChecker to query the grid. You are trying to create a fluent interface that reads easily from left to right.

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(DiagonalWinningLineChecker))]

public class when_checking_if_game_has_a_3_in_a_diagonal_line

{

private It should_check_for_3_O_tokens_from_right_to_left_diagonally

= () =>

{

grid.square_at(coordinate_0_1).contains_token_matching(Tokens.o_token);

grid.square_at(coordinate_1_1).contains_token_matching(Tokens.o_token);

grid.square_at(coordinate_2_2).contains_token_matching(Tokens.o_token);

};

}

}

The code should read as close possible to plain English from left to right. To make this fluent interface work, the grid must return an object that is capable of determining if the square at the coordinate contains a token that matches the token given. It makes sense that the object is a square.

Now that you have an idea of what the end result should look like, let's create the spec.

note

using Machine.Specifications;

using Wrox.BDD.Domain;

using Rhino.Mocks;

using NUnit.Framework;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(DiagonalWinningLineChecker))]

public class when_checking_if_game_has_a_3_in_a_diagonal_line

{

Establish context = () =>

{

grid = MockRepository.GenerateStub<Grid>();

square = MockRepository.GenerateStub<Square>();

coordinate_0_0 = new Coordinate(0, 0);

coordinate_1_1 = new Coordinate(1, 1);

coordinate_2_2 = new Coordinate(2, 2);

square.Stub(x => x.contains_token_matching(

Arg<Token>.Matches(c => c.Equals(Tokens.x_token)))).Return(true);

grid.Stub(x => x.square_at(Arg<Coordinate>

.Matches(c => c.Equals(coordinate_0_0)))).Return(square);

grid.Stub(x => x.square_at(Arg<Coordinate>

.Matches(c => c.Equals(coordinate_1_1)))).Return(square);

grid.Stub(x => x.square_at(Arg<Coordinate>

.Matches(c => c.Equals(coordinate_2_2)))).Return(square);

SUT = new DiagonalWinningLineChecker();

};

private Because of = () =>

{

result = SUT.contains_a_winning_line(grid);

};

private It should_check_for_3_X_tokens_from_left_to_right_diagonally

= () =>

{

grid.AssertWasCalled(x => x.square_at(

Arg<Coordinate>.Matches(c => c.Equals(coordinate_0_0))));

grid.AssertWasCalled(x => x.square_at(

Arg<Coordinate>.Matches(c => c.Equals(coordinate_1_1))));

grid.AssertWasCalled(x => x.square_at(

Arg<Coordinate>.Matches(c => c.Equals(coordinate_2_2))));

square.AssertWasCalled(x => x.contains_token_matching(

Arg<Token>.Matches(c => c.Equals(Tokens.x_token))),

o => o.Repeat.Times(3));

};

private It should_find_a_winning_line = () =>

{

Assert.That(result, Is.True);

};

private static DiagonalWinningLineChecker SUT;

private static Grid grid;

private static Square square;

private static bool result;

private static Coordinate coordinate_0_0;

private static Coordinate coordinate_1_1;

private static Coordinate coordinate_2_2;

}

}

Code file [when_checking_if_game_has_a_3_in_a_diagonal_line.cs] available for download at Wrox.com.

To make the fluent API work, you have introduced the concept of a Square. This represents the location for a given Coordinate.

The Square interface has a single method that determines if a given token matches the token that is occupying the square.

note

namespace Wrox.BDD.Domain

{

public interface Square

{

bool contains_token_matching(Token token);

}

}

Code file [Square.cs] available for download at Wrox.com.

The Grid also has an additional method added to its interface that returns a Square for a given Coordinate.

note

namespace Wrox.BDD.Domain

{

public interface Grid

{

void place_token_at(Coordinate coordinate, Token token);

bool contains_token_at(Coordinate coordinate);

GridView generate_grid_view();

Square square_at(Coordinate coordinate);

}

}

Code file [Grid.cs] available for download at Wrox.com.

With the modification to the Grid interface, you must also update the implementation, the NineSquareGrid. It needs to return an instance of the Square, so add a call to instantiate an as-yet nonexistent class.

note

namespace Wrox.BDD.Domain

{

public class NineSquareGrid : Grid

{

……

public Square square_at(Coordinate coordinate)

{

return new PlayingSquare();

}

}

}

Code file [NineSquareGrid.cs] available for download at Wrox.com.

Now, create the implementation of the Square interface and default the contains_token_matching to return false.

note

namespace Wrox.BDD.Domain

{

public class PlayingSquare : Square

{

public bool contains_token_matching(Token o_token)

{

return false;

}

}

}

Code file [PlayingSquare.cs] available for download at Wrox.com.

You can now update the DiagonalWinningLineChecker to use the new methods of the Grid and Square in order to match the expected behavior, as specified in your spec class.

note

namespace Wrox.BDD.Domain

{

public class DiagonalWinningLineChecker : LineChecker

{

public bool contains_a_winning_line(Grid tic_tac_toe_grid)

{

var coordinate_0_0 = new Coordinate(0, 0);

var coordinate_1_1 = new Coordinate(1, 1);

var coordinate_2_2 = new Coordinate(2, 2);

if (tic_tac_toe_grid.square_at(coordinate_0_0)

.contains_token_matching(Tokens.x_token) &&

tic_tac_toe_grid.square_at(coordinate_1_1)

.contains_token_matching(Tokens.x_token) &&

tic_tac_toe_grid.square_at(coordinate_2_2)

.contains_token_matching(Tokens.x_token))

return true;

return false;

}

}

}

Code file [DiagonalWinningLineChecker.cs] available for download at Wrox.com.

If you run the specification classes, all should pass.

You now must check that the implementation of the Grid interface can correctly return a PlayingSquare that confirms the existence of a token.

note

By now, you should have noticed that I write a method's name in lowercase with underscores to separate words. This is a design decision that I have taken to increase the readability of code, borrowed a little from Ruby as well. I have also thought hard about how I have named my methods in order to convey the behavior of the object to users of it. Remember, by creating code in a test-first process, you are able to create the best API you can, so I advise you take time to play with language in order to better communicate the behavior of objects in your solution.

Update the when_checking_for_a_token_on_the_grid with a new behavior that confirms the placement of a token.

note

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(NineSquareGrid))]

public class when_checking_for_a_token_on_the_grid

{

……

private It should_be_able_to_match_the_token = () =>

{

Assert.That(SUT.square_at(coordinate_with_token)

.contains_token_matching(Tokens.x_token), Is.True);

};

……

}

}

Code file [when_checking_for_a_token_on_the_grid.cs] available for download at Wrox.com.

The NineSquareGrid can now instantiate a PlayingSquare and pass in the Token at the given coordinate. Remember, this is only the happy-day scenario you are dealing with here, so you are not adding code to cover edge cases.

note

namespace Wrox.BDD.Domain

{

public class NineSquareGrid : Grid

{

……

public Square square_at(Coordinate coordinate)

{

return new PlayingSquare(_squares[coordinate.X, coordinate.Y]);

}

}

}

Code file [NineSquareGrid.cs] available for download at Wrox.com.

A PlayingSquare is another immutable value object, add a constructor that takes a token, which it then uses to perform an equality check with the passed-in token. Once the PlayingSquare is created, it cannot be modified.

note

namespace Wrox.BDD.Domain

{

public class PlayingSquare : Square

{

private readonly Token _token;

public PlayingSquare(Token token)

{

_token = token;

}

public bool contains_token_matching(Token token)

{

return _token.Equals(token);

}

}

}

Code file [PlayingSquare.cs] available for download at Wrox.com.

Your spec should pass. Now, let's get back to the edge case. What happens if there is no token for a given coordinate? Let's write a new behavior to verify what should happen.

note

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(NineSquareGrid))]

public class when_checking_for_a_token_on_the_grid

{

……

private It should_not_match_a_missing_token = () =>

{

Assert.That(SUT.square_at(coordinate_without_token)

.contains_token_matching(Tokens.o_token), Is.False);

};

……

}

}

Code file [when_checking_for_a_token_on_the_grid.cs] available for download at Wrox.com.

If you run the specs now, the code will throw an exception because there is no token at that coordinate that you can pass to the PlayingSquare.

You know the code is doing what you'd like to, so amend the NineSquareGrid class to check for a Token at the given coordinate, and, if no token exists, you can use a design pattern named the Null Object Pattern to create an EmptyPlayingSquare using a parameterless constructor.

note

namespace Wrox.BDD.Domain

{

public class NineSquareGrid : Grid

{

……

public Square square_at(Coordinate coordinate)

{

return contains_token_at(coordinate) ? (Square)

new PlayingSquare(_squares[coordinate.X, coordinate.Y]) :

new EmptyPlayingSquare();

}

}

}

Code file [NineSquareGrid.cs] available for download at Wrox.com.

The EmptyPlayingSquare simply returns false for a match on a token, and saves you from checking for nulls throughout your code.

note

namespace Wrox.BDD.Domain

{

public class EmptyPlayingSquare : Square

{

public bool contains_token_matching(Token o_token)

{

return false;

}

}

}

Code file [EmptyPlayingSquare.cs] available for download at Wrox.com.

This completes the list of behaviors for the scenario.

Run the specs and all should pass. Now, you should be done with this scenario, so let's run the UAT specs to see if you are good. Ooops! Looks like you have an error!

You were expecting player X to win, but the output is that player O has won. It looks as though the current player is being updated even though the game has ended. Let's write a spec to ensure that the TicTacToe game doesn't update the current player in the event of the player winning.

note

using Machine.Specifications;

using Wrox.BDD.Domain;

using NUnit.Framework;

using Rhino.Mocks;

namespace Wrox.BDD.Specs.Core.Domain_Specs

{

[Subject(typeof(TicTacToe))]

public class when_placing_a_winning_token_on_the_board : with_a_tictactoe_game

{

Establish context = () =>

{

coordinate_text = "1,1";

coordinate = Coordinate.parse(coordinate_text);

line_checker.Stub(x =>

x.contains_a_winning_line(Arg<Grid>.Is.Anything))

.Return(true);

player_tracker.Stub(x => x.current_player()).Return(Tokens.x_token);

};

private Because of = () =>

{

SUT.place_token_for_current_player_at(coordinate);

};

private It should_not_alternate_the_player = () =>

{

player_tracker.AssertWasNotCalled(x => x.finish_players_move());

};

private static Coordinate coordinate;

private static string coordinate_text;

}

}

Code file [when_placing_a_winning_token_on_the_board.cs] available for download at Wrox.com.

And now, simply implement the behavior in TicTacToe class.

note

namespace Wrox.BDD.Domain

{

public class TicTacToe : Game

{

……

public void place_token_for_current_player_at(Coordinate coordinate)

{

_grid.place_token_at(coordinate, current_token());

if (!the_current_player_has_won_the_game())

_player_tracker.finish_players_move();

}

……

}

}

Code file [TicTacToe.cs] available for download at Wrox.com.

Run all of you specs. Great! They all pass! Let's see the code in production.

Integrating the Winning a Game with Three in a Row Scenario

There's nothing extra you must do in terms of integration, apart from simply running the game. If you put three X tokens in a diagonal line from left to right, you will find that the game ends. However, no other winning variations will cause the game to finish, and there is nothing to stop tokens from being placed on top of each other, or on invalid squares.

You have added a fair bit of behavior for the game thus far, and even though you have a lot left, the most important thing is that your customer can see the progress you've made. He can start to play the game and get a feel for the software. By choosing to build vertical slices of functionality rather than layers, you can get working software in front of the customer quickly for valuable feedback.

Completing the Game

Unfortunately, this is where this chapter leaves the TicTacToe code kata. However, as an exercise, I strongly suggest that you complete the game by adding the remaining features in the manner you have been shown.

Along with the code download that accompanies this chapter, I have also added the complete source code for the finished game that you can use to compare against how you may have designed the remaining features.

Moving Forward

You should experiment more with code katas to better understand BDD and the importance of focusing on the language of the domain you work within, all of which can help you become a better developer.

Figure 14.26 shows the Agile Manifesto, the four principles that are the cornerstone to producing better software. After reading the manifesto, you should see how user stories and BDD support a more agile development process.

Figure 14.26 Agile Manifesto

14.26

Summary

This chapter dealt with the need to focus on the behavior of a system under development, rather than its technical details, to meet and exceed the needs of a customer. To better capture the behaviors of a system under development, you were introduced to user stories that emphasized the communication between the development team and the customer, as an alternative method to the traditional requirements gathering, which places more value on written documentation.

User stories enable you to capture just enough about a feature so that you can estimate complexity and have a conversation with the customer about the details of the feature at a later date. From user stories, acceptance criteria are born using the “Given, When, Then” template, which enables the details of features to be explored and verified.

The second part of this chapter introduced you to Behavior Driven Development (BDD), which has evolved out of a need for Test-Driven Development (TDD) to take a step back to avoid losing focus on what the system under development wants to achieve. Outside-in development further emphasizes the need to drive development from features that a customer can benefit from, and when used with TDD, can be a powerful force for software development.

In the final part of the chapter, you worked through the capturing of features for a Tic-Tac-Toe game via user stories and the development of it using SpecFlows BDD framework for specifying application behavior, and MSpec for specifying object behavior. This exercise underlined the effectiveness of BDD and user stories in software development to produce quality software.

By applying the techniques found in this chapter, in conjunction with listening to your customers and working with them to understand their visions and goals, you will be in a better place to write software that exceeds their expectations, which will make your job a whole lot easier.

About the Author

Scott Millett works in London, England, for Wiggle.co.uk, an e-commerce company specializing in cycle and triathlete sports. He has been working with .NET since version 1.0, and was awarded the ASP.NET MVP in 2010, and again in 2011. He is the author of Professional ASP.NET Design Patterns (Indianapolis: Wiley, 2010) and the co-author of Professional Enterprise.NET (Indianapolis: Wiley, 2009). When not writing about or working with .NET, he can be found relaxing and enjoying the music at Glastonbury and all of the major music festivals in the United Kingdom during the summer. If you would like to talk to him about this chapter, anything .NET, or the British music festival scene, feel free to write to him at scott@elbandit.co.uk, or by giving him a tweet @ScottMillett.