phpspec+behat: The Bowling Game Kata

behat phpspec bowling kata

A week ago, I announced on Twitter new blogpost about CQRS. I’m still writing it but I needed a little break from it and to take something new, something that I wanted to learn, try from a long time. I did my first Kata.

Kata is a Japanese word and could mean “practicing move”. Programmers adapted that word and created a lot of Katas (exercises) to improve their skills. One of the most popular Kata is The Bowling Game described by Robert Cecil Martin (Uncle Bob). The clue is to create an algorithm which shows score using the rules in this sport’s discipline.

On Saturday, I took my MacBook Pro and went to a cafe. I ordered, as usually, a large cappuccino without sugar and with non-fat milk and I’ve started two hours coding session.

The rules

As a person who grew in Poland, I didn’t know the rules in bowling, although I’ve played three times on it.

  1. There are 10 frames. In each frame, you have 2 moves, except the last frame when you could have 3 moves.
  2. When you knocked down 10 pins in 2 moves in 1 frame, you have “spare”. Then next move is doubled to score.
  3. When you knocked down 10 pins in 1 move in 1 frame, you have “strike”. Then next two moves are doubled to score.
  4. If in the last frame, you have “spare” or “strike” then you have one extra move in this frame.
  5. Maximum score you can achieve is 300.

The tools to TDD, BDD

The rules are plain and clear now, so I could practice my skills in TDD, especially using tools to specs and BDD. I’ve chosen phpspec for specs, and behat for BDD tests.

phpspec

Is a great tool if you want to create good code from the beginning. You are describing behaviour of your object which you will create. phpspec creates for you php code based on your specification, and after it, you add an only implementation.

behat

Behat allows you create scenarios (in natural language) which represent the behaviour from the business side. In this case, the “business side” are rules in a bowling game.

Installation phpspec and behat

I don’t want to describe here each line that I’ve written. I push everything to GitHub repository, but to make this blognote more useful, I will explain how to add phpspec and behat to your project.

First, what you need is Composer. If you don’t know what it is, let’s go to one of my previous notes. I’ve described what it is, how to install and how to use. Enjoy!

Installing and using behat

We need to run two commands, first get behat code from a repository, and second create needed files in your project:

composer require behat/behat # get behat code
vendor/bin/behat --init # create needed files

It creates new folder features when you should storage your scenarios. You can watch how it looks in my project.

To run your scenarios, you need run only one command:

vendor/bin/behat

And this is it!

Installing and using phpspec

Installation phpspec is a bit difficult than behat but still easy. We have to start with getting a code from a repository, so let’s use composer.

composer require phpspec/phpspec

Then, you need edit your composer.json file and add there following lines before last }

	,
	"autoload": {
    "psr-0": {
      "": "src/"
    }
	}

Using phpspec required the knowledge of two commands, it’s desc and run. About it, you can read in official documentation.

Last words

If you want to create your bowling code, you can use my scenarios that I’ve described for behat.

Make fun!

	Feature: Score
	
	  Scenario: Two moves with each two shot pins
	    When In move user shot "2" pins
	    And In move user shot "2" pins
	    Then The score is "4"
	    
	  Scenario: Two moves with two different shot pins
	    When In move user shot "2" pins
	    And In move user shot "3" pins
	    Then The score is "5"
	    
	  Scenario: Four moves in two frame
	    When In move user shot "2" pins
	    And In move user shot "3" pins
	    And In move user shot "4" pins
	    And In move user shot "5" pins
	    Then The score is "14"
	    And The frame is "3"
	    
	  Scenario: One move with shot all pins
	    When In one move user shot strike
	    Then The frame is "2"
	    
	  Scenario: In first frame user shot 10 pins and do next move
	    When In two moves user shot spare
	    Then The frame is "2"
	    And In two moves user shot spare
	    Then The score is "25"
	    
	  Scenario: In first frame user shot 10 pins in one move and do next move
	    When In one move user shot strike
	    Then The frame is "2"
	    And In move user shot "4" pins
	    And In move user shot "5" pins
	    Then The score is "28"
	
	  Scenario: In first frame user shot 10 pins in one move and do next moves in two frames
	    When In one move user shot strike
	    Then The frame is "2"
	    And In move user shot "4" pins
	    And In move user shot "5" pins
	    Then The score is "28"
	    And In move user shot "4" pins
	    And In move user shot "5" pins
	    Then The score is "37"
	
	  Scenario: In two frames user shot 10 pins in first move
	    When In one move user shot strike
	    Then The frame is "2"
	    And In one move user shot strike
	    Then The frame is "3"
	    And The score is "30"
	    
	  Scenario: In all frames user shot all pins in first move
	    When In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    And In one move user shot strike
	    Then The score is "300"
	
	  Scenario: In two frame user shot all pins and do next move
	    When In two moves user shot spare
	    Then The frame is "2"
	    And In two moves user shot spare
	    Then The score is "25"
	    And In move user shot "4" pins
	    And In move user shot "5" pins
	    Then The score is "38"
	
	  Scenario: In two frame user shot all pins and do next move
	    When In one move user shot strike
	    Then The frame is "2"
	    And In two moves user shot spare
	    And In move user shot "2" pins
	    And In move user shot "4" pins
	    Then The score is "38"