Articles Feed

Authors

Categories

Limelight Tutorial: Tic Tac Toe Example

by: paul | September 29th, 2008 | 0 comments »

Welcome to a Limelight production. I am going to go through a step by step introduction to limelight development using a tic tac toe game as an example. So, lets get started. I am going to create the directory structure and open it up in a text editor.

  1. $ mkdir tictactoe
  2. $ cd tictactoe
  3. $ mate .

Now I need to set up Limelight. You can just download the gem.

  1. $ jruby -S gem install limelight

We can start by creating the props.rb file in the tictactoe directory. The props.rb file defines the structure of your application. A prop is named after the theater metaphor. We are going to use them to define what our scene's physical structure look like. We can start with a simple screen with an empty board with the nine cells we need for a tic tac toe game. Lets create a spec directory to write a test for the props we are going to create.

  1. $ mkdir spec
  2. $ mkdir spec/props

Now for the spec. In the spec directory, we can name our spec props_spec.rb. We want to check that there is a cell on the scene. Here is the first test. NOTE: To be able to run the test, you will need the spec_helper.rb in your spec directory (not the props directory). You can copy it from the sample application.

  1. require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
  2. describe "Props" do
  3. include PropSpecHelper
  4. before(:each) do
  5. setup_prop_test
  6. end
  7. it "should have cell_0_0" do
  8. @scene.find("cell_0_0").should_not be(nil)
  9. end
  10. end

and when we run it (You can copy the Rakefile from the sample application as well, if you want to have a specs task),

  1. $ jruby -S rake spec

we get the failure

1) Errno::ENOENT in 'Props should have cell_0_0' No such file or directory - File not found - /Users/paulwpagel/Desktop/tictactoe/props.rb /Users/paulwpagel/Desktop/tictactoe/spec/spec_helper.rb:18:in `initialize' /Users/paulwpagel/Desktop/tictactoe/spec/spec_helper.rb:18:in `setup_prop_test' /Users/paulwpagel/Desktop/tictactoe/./spec/props/props_spec.rb:6: Finished in 0.063 seconds 1 example, 1 failure

So, lets create the props.rb file in the project root. Now we should get the error.

1) 'Props should have cell_0_0' FAILED expected not nil, got nil /Users/paulwpagel/Projects/tictac/./spec/props/prop_spec.rb:12: Finished in 0.089 seconds 1 example, 1 failure

Each of the props accepts a block of code your can give options/structure to. We can open the props.rb file and add a cell with the id of "cell_0_0" to make this test pass.

  1. main do
  2. board do
  3. cell :id => "cell_0_0"
  4. end
  5. end

And the test passes. Lets make sure we have the rest of the id's while we are at it. Here is a more exhaustive spec.

  1. it "should have cells" do
  2. @scene.find("cell_0_0").should_not be(nil)
  3. @scene.find("cell_0_1").should_not be(nil)
  4. @scene.find("cell_0_2").should_not be(nil)
  5. @scene.find("cell_1_0").should_not be(nil)
  6. @scene.find("cell_1_1").should_not be(nil)
  7. @scene.find("cell_1_2").should_not be(nil)
  8. @scene.find("cell_2_0").should_not be(nil)
  9. @scene.find("cell_2_1").should_not be(nil)
  10. @scene.find("cell_2_2").should_not be(nil)
  11. end

And it fails in a similar manner. Lets expand our props.rb file to make the test pass.

  1. main do
  2. board do
  3. cell :id => "cell_0_0"
  4. cell :id => "cell_0_1"
  5. cell :id => "cell_0_2"
  6. cell :id => "cell_1_0"
  7. cell :id => "cell_1_1"
  8. cell :id => "cell_1_2"
  9. cell :id => "cell_2_0"
  10. cell :id => "cell_2_1"
  11. cell :id => "cell_2_2"
  12. end
  13. end

And it passes. However, it is all ruby code, so I can leverage ruby functions to help me out. Lets remove the duplication.

  1. main do
  2. board do
  3. 3.times do |row|
  4. 3.times do |col|
  5. cell :id => "cell_#{row}_#{col}"
  6. end
  7. end
  8. end
  9. end

Much better. Lets now move on to the styles. Nothing will show up without a few styles. I create a styles.rb file in the project root and filled it with some simple content. In Limelight, styles refer to how a prop is aesthetically displayed on the screen. Here is an example which defines the size and gives a border to the board and the cells.

  1. board {
  2. width 152
  3. height 152
  4. border_width 1
  5. border_color "black"
  6. }
  7. cell {
  8. width 50
  9. height 50
  10. border_width 1
  11. border_color "black"
  12. }

We should be able to start up Limelight and see the board. We start Limelight like: (From the tictacctoe directory)

  1. $ jruby -S limelight open .

and there is your first Limelight screen. Pretty easy, and all ruby code. Lets make it more interesting. Let us make it such that if you click on one of the squares, the square shows the 'X' mark denoting the first move.

First we create a directory called players. Inside go the players, which contain the actions and behavior of the props for a Limelight scene (the controllers).

  1. $ mkdir players

We want to now make a player for the cell prop. We create a file inside of the players directory called cell.rb. The file will start with a definition by looking like:

  1. module Cell
  2. end

We define all players in modules of the same name as the file and prop, by convention. This allows Limelight to include this behavior when it needs it. You can specify specific mappings between the props and its players, but we don't need to do that here. So, let's make the cell more interesting. When we click on the cell, we want it to make a large 'X' mark. Lets start by creating a spec for the behavior.

I created a new directory for the players spec

  1. $ mkdir spec/players

We have to add the players directory to the ruby search path, so I added the following line to the spec_helper.

  1. $: << File.expand_path(File.dirname(__FILE__) + "/../players")

My spec is going to find the prop that was clicked on and make that prop display an 'X', denoting the first move. Here is what my first spec looks like (I call it cell_spec.rb):

  1. require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
  2. require 'cell'
  3. describe Cell do
  4. include Cell
  5. attr_accessor :id
  6. it "should make first move an X" do
  7. @id = "cell_0_0"
  8. @cell_one = Limelight::Prop.new
  9. @scene = MockScene.new
  10. @scene.register("cell_0_0", @cell_one)
  11. self.stub!(:scene).and_return(@scene)
  12. mouse_clicked(nil)
  13. @cell_one.text.should == "X"
  14. end
  15. end

Which provides the feedback when run:

F 1) NoMethodError in 'Cell should make first move an X' undefined method `mouse_clicked' for # /Users/paulwpagel/Projects/tictac/spec/players/cell_spec.rb:14: Finished in 0.007423 seconds 1 example, 1 failure

If you have seen a rSpec specification before, this should look syntactically familiar. Before we move on to making the test pass, let us take closer look at a few aspects.

@id = "cell_1_1" - This line is setting the id of the imaginary prop that the players behavior will be executed against. @scene = MockScene.new - This creates a scene to mock out. The scene will be explained later, but for this test we are going to use the find method on scene to find our props. @cell_one = MockProp.new - Create a mock prop that will turn to 'X' when clicked @scene.register("cell_1_1", @cell_one) - We are giving the scene the mock prop, so the find method will find it by its id. mouse_clicked(nil) - Simulates a mouse_click on the cell. It takes an event, but we don't care about that yet, so lets just pass in nil.

All right, time to make this test pass. Lets open up the cell.rb player and see what we need done to make the test pass.

  1. module Cell
  2. def mouse_clicked(event)
  3. cell_prop = scene.find(id)
  4. cell_prop.text = "X"
  5. end
  6. end

Run the test again, no failures. We needed to find the prop on the screen which we are concerned about. We do this by calling find on a method scene, which will give us any prop by its unique identifier. We are looking for the id of the element we clicked, and then we set the text of that element to 'X', which makes the test satisfied.

Now, we can run the application from the root directory.

  1. $ jruby -S limelight open .

If we click on the box that is displayed, a small 'X' should appear in the upper right corner.

Congratulations, that is your first piece of Limelight behavior. However, this is not very interesting yet. Lets take it the next step and make the tic tac toe game work. I am going to create a lib directory to hold the game model.

  1. $ mkdir lib
  2. $ mkdir spec/lib

And before I write my first spec, I am going to add the new lib directory to the ruby search path by adding the following line to the spec_helper (It is already in the example spec_helper.rb, you don't need to add it).

  1. $: << File.expand_path(File.dirname(__FILE__) + "/../lib")

So, here is what my first spec looks like:

  1. require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
  2. require 'game'
  3. describe Game do
  4. it "make a move in the middle square" do
  5. game = Game.new
  6. game.move(1, 1)
  7. game.mark_at(1, 1).should == "X"
  8. end
  9. end

To make it pass, we need to create a game class in the lib directory and give it this code.

  1. class Game
  2. def move(row, column)
  3. end
  4. def mark_at(row, column)
  5. return "X"
  6. end
  7. end

And we can follow the test driving of the model to make the game class. I have already done this, and you can download the models in the sample application. Lets move past that back to the players and hook up the game.

I am going to create a file init.rb in the root directory. The init.rb class gets loaded up by Limelight when you start the application. We want to create a new game and have a way to keep it in memory for the other classes to use. Here is what the spec looks like in a init_spec.rb in the spec directory:

  1. require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
  2. require "game"
  3. describe "init" do
  4. it "should create new game on initialization" do
  5. game = mock('game')
  6. Game.should_receive(:new).and_return(game)
  7. Game.should_receive(:current=).with(game)
  8. require File.expand_path(File.dirname(__FILE__) + "/../init")
  9. end
  10. end

The simplest way to start that is to have a current_game class variable. Here is the code for the init.rb.

  1. $: << File.expand_path(File.dirname(__FILE__) + "/lib")
  2. require "game"
  3. Game.current = Game.new

I add the lib directory to the ruby search path so the Limelight application would know what a game is when I require it.

Now we need to plug the game model into the cell player. Lets change the spec we made earlier to make the first move depending on the game model. Here is the new version.

  1. it "should make first move in a game" do
  2. @id = "cell_0_0"
  3. @cell_one = Limelight::Prop.new
  4. @scene = MockScene.new
  5. @scene.register("cell_0_0", @cell_one)
  6. self.stub!(:scene).and_return(@scene)
  7. game = mock('game')
  8. Game.should_receive(:current).and_return(game)
  9. game.should_receive(:move).with(0, 0)
  10. game.should_receive(:mark).and_return("X")
  11. mouse_clicked(nil)
  12. @cell_one.text.should == "X"
  13. end

I am mocking out the game model and passing the values from the id into the game's move method. Here is the code that makes this pass.

  1. module Cell
  2. def mouse_clicked( event)
  3. game = Game.current
  4. x, y = get_coordinates
  5. game.move(x, y)
  6. cell_prop = scene.find(id)
  7. cell_prop.text = game.mark
  8. end
  9. private ################################
  10. def get_coordinates()
  11. x = id[(id.length - 1)..(id.length - 1)].to_i
  12. y = id[(id.length - 3)..(id.length - 3)].to_i
  13. return x, y
  14. end
  15. end

Minus the ugly string manipulation, it is a pretty straight forward approach. Now we should be able to start up the application and click on any of the squares and make some moves. There are 2 things left to do for this demo. We need to make sure that a player can not move on a square that is already occupied, and we need to display a winner. So for the first task, we need to write a spec to have some kind of feedback to the players that the move is invalid. Let's add this spec to the props_spec file.

  1. it "should have message center for feedback to the user" do
  2. @scene.find("message_center").should_not be(nil)
  3. end

Nice and simple. Here is the new props.rb file.

  1. main do
  2. board do
  3. 3.times do |row|
  4. 3.times do |col|
  5. cell :id => "cell_#{row}_#{col}"
  6. end
  7. end
  8. end
  9. end
  10. message_center :id => "message_center"

Now lets write a spec for the cell_spec to make sure that the move is valid, else we display a message in the message center to the user they must move somewhere else. Here is the spec.

  1. it "should display in the message center if the space is occupied." do
  2. @id = "cell_0_0"
  3. @cell_one = Limelight::Prop.new
  4. @message_center = Limelight::Prop.new
  5. @scene = MockScene.new
  6. @scene.register("cell_0_0", @cell_one)
  7. @scene.register("message_center", @message_center)
  8. self.stub!(:scene).and_return(@scene)
  9. game = mock('game')
  10. Game.should_receive(:occupied?).with(0, 0).and_return(true)
  11. mouse_clicked(nil)
  12. @message_center.text.should == "This space is occupied, please move in an unoccupied square"
  13. end

Same as before, with a new prop added. Here is the new cell.rb file.

  1. module Cell
  2. def mouse_clicked( event)
  3. game = Game.current
  4. x, y = get_coordinates
  5. if game.occupied?(x, y)
  6. message_center = scene.find("message_center")
  7. message_center.text = "This space is occupied, please move in an unoccupied square"
  8. else
  9. game.move(x, y)
  10. cell_prop = scene.find(id)
  11. cell_prop.text = game.mark
  12. end
  13. end
  14. private ################################
  15. def get_coordinates()
  16. x = id[(id.length - 1)..(id.length - 1)].to_i
  17. y = id[(id.length - 3)..(id.length - 3)].to_i
  18. return x, y
  19. end
  20. end

Simple if, makes it all work. Lets remove the duplication in the specs. Here is the new spec file.

  1. require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
  2. require 'cell'
  3. describe Cell do
  4. include Cell
  5. attr_accessor :id
  6. before(:each) do
  7. @id = "cell_0_0"
  8. @cell_one = Limelight::Prop.new
  9. @scene = MockScene.new
  10. @message_center = Limelight::Prop.new
  11. @scene.register("message_center", @message_center)
  12. @scene.register("cell_0_0", @cell_one)
  13. self.stub!(:scene).and_return(@scene)
  14. @game = mock('game', :occupied? => false)
  15. Game.should_receive(:current).and_return(@game)
  16. end
  17. it "should make first move in a game" do
  18. @game.should_receive(:move).with(0, 0)
  19. @game.should_receive(:mark).and_return("X")
  20. mouse_clicked(nil)
  21. @cell_one.text.should == "X"
  22. end
  23. it "should display in the message center if the space is occupied." do
  24. @game.should_receive(:occupied?).with(0, 0).and_return(true)
  25. mouse_clicked(nil)
  26. @message_center.text.should == "This space is occupied, please move in an unoccupied square"
  27. end
  28. end

Much better. Now lets do the case of a winner. Here is the spec for the cell.

  1. it "should display there was a winner in the message center" do
  2. @game.should_receive(:move).with(0, 0)
  3. @game.should_receive(:is_winner?).and_return(true)
  4. mouse_clicked(nil)
  5. @message_center.text.should == "Player X has won the game, congratulations"
  6. end

And here is the new cell.rb

  1. module Cell
  2. def mouse_clicked( event)
  3. game = Game.current
  4. x, y = get_coordinates
  5. if game.occupied?(x, y)
  6. message_center.text = "This space is occupied, please move in an unoccupied square"
  7. else
  8. game.move(x, y)
  9. cell_prop = scene.find(id)
  10. cell_prop.text = game.mark
  11. message_center.text = "Player #{game.mark} has won the game, congratulations" if game.is_winner?
  12. end
  13. end
  14. private ################################
  15. def get_coordinates()
  16. x = id[(id.length - 1)..(id.length - 1)].to_i
  17. y = id[(id.length - 3)..(id.length - 3)].to_i
  18. return x, y
  19. end
  20. def message_center
  21. return scene.find("message_center")
  22. end
  23. end

Now we can finish off the application by adding new game functionality, or even a computer player that can not be beaten! However, before I let you go, we have to add some styles to the message center and pretty up the board to make it look better. To find a comprehensive list of the styles supported in Limelight, go here(http://limelightwiki.8thlight.com/index.php/Style_Attributes). Here is a new version of the styles.rb.

  1. main {
  2. width "100%"
  3. horizontal_alignment "center"
  4. }
  5. board {
  6. width 152
  7. height 152
  8. border_width 1
  9. border_color "black"
  10. }
  11. cell {
  12. width 50
  13. height 50
  14. border_width 1
  15. border_color "black"
  16. }
  17. message_center_container{
  18. top_margin 100
  19. width "100%"
  20. horizontal_alignment "center"
  21. }
  22. message_center {
  23. width 300
  24. height 100
  25. rounded_corner_radius "10"
  26. border_color "black"
  27. border_width 2
  28. padding 5
  29. }

There was one change to the props.rb file, to wrap the message_center in a prop called message_center_container. Also, notice the pretty rounded corners. Easy to do.

Here is the props.rb

  1. main do
  2. board do
  3. 3.times do |row|
  4. 3.times do |col|
  5. cell :id => "cell_#{row}_#{col}"
  6. end
  7. end
  8. end
  9. end
  10. message_center_container do
  11. message_center :id => "message_center"
  12. end

Happy Limelight coding!

Pair Me Up

by: paul | June 14th, 2007 | 15 comments »

I am a better pair than solo developer. For me, software is a collaborative art from the start to the end. Starting from the beginning of a project, where the developers need to collaborate with the customer s and stakeholders of the project to learn about the business domain. Then working with the project manager for sorting priorities and deadlines to make the business goals realizable in the fastest amount of time. Also development is collaboration, via pair programming, to produce a dialog between the developers on their vision of the implementation of this code. The last part, pair programming, is what I would like to focus on.

Having a pair has the traditional advantages of keeping disciplined and sharing the knowledge base. That is a starting point, but pairing is quintessentially important to my process due to the diversity it provides. A diversity of approach and implementation provide me with enough to perform at a highly creative and expressive manner.

Since you are not driving the keyboard and control of the computer, there is more time for contemplating code you wrote and direction you are moving. Most of my good ideas come from the time when someone else is typing. Since I was just working on the practical, I have my head wrapped around the code, and since I am not responsible for typing, I can reflect in the abstract.

I have heard many places that a benefit of test driven development is that the tests force you to design the API of the objects you are using as someone would use them. Well, pair programming, in compliment with programming ping-pong, forces your code to be clean. When you write a test, it isn’t you that makes it pass, so you have to think with expression and intent in mind. So, you end up writing the test FOR your pair. It becomes a form of writing, not just coding.

Sometimes, the test needs to be explained. While explaining something to a pair, your test must hold up your own arguments. Often times when I come to explain something I just wrote, I think of a better way to do it. Explanation is the best form of validating you understand where you are going well.

Also, pairing is how I learned most of my developer personality. Taking bits and pieces of the traits of my pairs through years of pairing. My style is a composite of pairing with various mentors and peers of mine. It has shown me how people approach this craft.

Three Reasons to Use FitNesse

by: micah | January 19th, 2007 | 3 comments »

1. You find your self delivering software to your customer who says “That’s not what I asked for.”

Using FitNesse allows you to communicate with the customer up front. Before a line of code is written, you can have all the behavior expressed in an executable format. Make sure the customer helps to write these tests. Once your FitNesse test is in place, all you need to do it make it pass. Due to the cut-and-dry aspect of executable specifications (FitNesse test), one the spec is passing, you have delivered precisely what your customer asked for.

2. Bugs sneak into your system as development progresses and these bugs takes weeks to find and remove.

FitNesse is a tools to help you drive development with tests. When practices with discipline, test driven development will insure that you have a FitNesse test for each and every feature in your system. The moment a bug is introduced, you will know about it because a FitNesse test will fail.

3. It is difficult to create documentation for your system and it is constantly out of date because the system is changing.

FitNesse offers a unique documentation solution. When ever you write a FitNesse test, you are in fact describing how the system works. In other words you’re documenting it. The web/wiki based nature of FitNesse makes documentation simple and convenient. The best part is that the documentation in FitNesse can never go out of date. Since you’re keeping your test passing, and your tests are documentation, it’s impossible for them to lie.


There is an article I wrote about FitNesse for Windows Developer Power Tools. This book, just released today, includes articles on dozens of free tools that .NET developers might benefit from. If you write .NET code, check it out. If not, keep in mind that FitNesse will work for almost any language.

Getting started with Rails and FitNesse

by: paul | January 15th, 2007 | 36 comments »

This is intended to be a tutorial to get you started using FitNesse with ruby on Rails. There is some explanation needed about FitNesse, Fit, and Rails. Smart people have written about such things, I will leave you to google them as interested. Two good references are listed at the bottom of this tutorial.

So lets get started. Our customer has just written a test that looks like this:
|vending machine|
|check|amount|$0.00|
|enter|currency|$.35|
|press|add change|
|check|amount|$.35|
|enter|selection|juicy fruit|
|press|vend|
|check|amount|$0.00|

This would be a common first fixture for a product, as it is limited in scope, it is a very specific example from which to build a conversation about requirements about. Anyway, the first thing to making this pass is getting some of the FitNesse infrastructure in place around your rails app.
First, lets create a rails app for our vending machine
$rails vending_machine

We see all the normal rails stuff, all the creates.
Lets download FitNesse and place it in our vending_machine root directory. FitNesse can be downloaded at http://fitnesse.org. And start the FitNesse server.
So, now we go to the FitNesse main page and create the page for our acceptance test. Then put the test from the customer into the page and try to run it. Failures? We need to set up the environment to run with ruby fit. Follow the instructions here (http://fitnesse.org/FitServers.RubyFit) to set up the right test runner for ruby.
Lets write our first fixture in a fixtures directory we create in the root folder.
Our new test with the path and test runner set up looks like this
!define COMMAND_PATTERN {ruby -I%p ruby/bin/FitServer.rb}
!path 

!3 Make one transaction with a vending machine
!|fixtures.VendingMachine| |check|amount|$0.00| |enter|currency|$.35| |press|add change| |check|amount|$.35| |enter|selection|juicy fruit| |press|vend| |check|amount|$0.00|
There are a few things to notice about the changes.
* The path is the rails root dir.
* Fixtures.VendingMachine is mapping to the folder name/module name of where the fixutures are located. In this instance it is a folder in the rails directory called fixtures.
* If you run the test, you will get all sorts of exceptions, because the fixture code is not written yet.
Note: If the table is not even showing up when you run the fixture go here.
Now it is time to write a fixture to make this test fail without any exceptions. In the fixtures directory, create a file called vending_machine.rb. The naming of your fixtures maps with the name of your file, which it will require. Lets make a stub file to make the test fail without exceptions.
require 'ruby/lib/fit_helper'
module Fixtures
  class VendingMachineFixture < Fit::ActionFixture
    attr_accessor :currency, :selection
    
    def initialize
      super
      @@actor = self
    end
    
    def add_change
    end
    
    def vend
    end
   
  end
end

Now we should have failures with the amount not changing.
Lets create our controller for the vending machine and start to implement the code. I am going to leave out the specs I use to write the controller, just show the code. Here is the first version of the controller. Note it has the same stubbed methods the fixture has.
class VendingMachineController < ApplicationController
  def add_change
  end
  def vend
  end
end

Lets hook up the fixture to the imaginary controller. There is a fair amount of set up which is rails related.
First, we need to load up the environment and the controllers. Add these lines to the beginning of your fixture.
require File.expand_path(File.dirname(__FILE__) + "/config/environment")
require File.expand_path(File.dirname(__FILE__) + '/app/controllers/application')

Which should allow us to change the initialize method to:
def initialize
      super
      @@actor = self
      @controller = VendingMachineController.new
      @controller.params = {}
    end

Which creates the controller, and initializes its params to an empty dictionary. There are other ways to do this, like creating test params, but for simplicity, we are going to create our own for now.
Next, we set up the values in the params and call the controller methods.
    def add_change
      @controller.params[:amount] = @currency
      @controller.add_change  
    end
    
    def vend
      @controller.params[:selection] = @selection
      @controller.vend
    end

Now, we make the test pass by implementing the controller.
class VendingMachineController < ApplicationController
  
  def initialize
    @items = {"juicy fruit" => 35 , "doublemint" => 45 }
    @session = {} if not @session
    @session[:amount_entered] = 0.0;
  end
  
  def add_change
    @session[:amount_entered] += params[:amount].to_f
  end
  
  def vend
    @items.each_pair do |key, value|
      if(params[:selection] == key)
        @session[:amount_entered] = 0.0
      end
    end
  end
end


Missing Requires

There is some weirdness around the way RubyFit collects exceptions after failing to find the file to require. If this occurs, dig into ruby fit’s FixtureLoader, specifically the find_class method. Usually you can get some information from the exceptions being silently caught.

References

http://fit.rubyforge.org/basics.html - RubyFit http://www.cornetdesign.com/2005/12/fitnesse-and-ruby-basic-tutorial.html - Fitnesse and Ruby

BOC

by: micah | November 12th, 2006 | 1 comments »

BOC (Build Operate Check) n. : The typical flow of an automated test*

BOC is a testing pattern that Unclebob briefly mentioned on fitnesse.org shortly after it was published. It describes the typical steps taken in an automated test.

Experienced test writer use BOC whether they know it or not. For new-commers to automated testing, BOC is lesson #1.

If you think about it, BOC is very logical. Every test is testing something; some Operation that the system under test (SUT) performs. That’s where the Operate step comes from.

In almost all cases, you can’t just invoke the operation. The automated test Builds a testable environment first. Maybe data needs to be put in a database, or a service layer needs to be started. Either way, the Build step comes first.

After invoking the Operation, a test needs to Check that it behaved as expected. Clearly, the Check step has to come last.

Example:

Consider a test for the Withdraw feature of an ATM machine.

Build:

Operate:

Check:

Next time you’re writing an automated test, think about it. More likely than not, you’re using BOC.

Self Shunt

by: paul | September 11th, 2006 | 34 comments »

The self-shunt method of testing has been conflicting for me. Self-shunt is a good testing pattern to test observers/views. A colleague of mine has started to convince me that self-shunt has some serious drawbacks. I want to explore the different ways to address the same pattern and how they fit into the test process and the test content. Are certain patterns easier to write and certain ones have a better final form?

Lets look at some code from Michael Feathers self shunt paper (see bottom for link). I extended it to do the mocking examples. The user story we are working with is the name of an item must be displayed on the led when the item is scanned.

Writing all of the tests did not require a concrete window (Display). We didn’t need to create the stub of the file to use; we could just use the interface. All the test patterns let the test be isolated in the test class/interface/production class triad. As a developer, it is easier for me to produce faster without quality loss if my context of thought is limited as much to the scope of the test as possible. Each extra window I switch is more contexts to deal with.

Here are three different tests:

  1. public class ScannerTest extends TestCase implements Display
  2. {
  3. private Item lastItem;
  4. public void testScan()
  5. {
  6. Item item = new Item("corn flakes");
  7. Scanner scanner = new Scanner(this);
  8. scanner.scan(item);
  9. assertEquals(item,lastItem);
  10. }
  11. public void displayItem(Item item)
  12. {
  13. lastItem = item;
  14. }
  15. }

The first test is making user of self-shunt test. Self-shunt was a quick way to start writing a test. The implementation on the interface in the test class will give you a good idea on what the implementation of the concrete class should look like when you get there. Also, the test is simple and the syntax is expressive. However, the scalability is questionable. If you had more than one self-shunted interface in a single test file, it would be hard to start differentiating between which variables are used in which. Also, moving around the file to get a good sense of what a test is doing is misdirectional and distracting. Ideally, I want to see the entire test on one screen, so I can read it. If there were many implemented methods in a test file that were not tests or helpers, there is the potential to be confused.

  1. public class ScannerTest extends TestCase
  2. {
  3. public void testScan()
  4. {
  5. Item item = new Item("corn flakes");
  6. Display mockDisplay = new MockDisplay();
  7. Scanner scanner = new Scanner(mockDisplay);
  8. scanner.scan(item);
  9. assertEquals(item,((MockDisplay)mockDisplay).lastItem);
  10. }
  11. }
  12. public class MockDisplay implements Display
  13. {
  14. public Item lastItem;
  15. public void displayItem(Item item)
  16. {
  17. lastItem = item;
  18. }
  19. }

Then I wrote the hand mock test. This test got rid of the clutter of implementing interfaces in the test and having local variables. Also, there are no external libraries needed, like a dynamic mocking library. The test is simple and easy to read. The biggest drawback is dealing with the hand mock test file. It is untested code that I have seen a tendency for behavior to slip into, which is disastrous. It can cause a bug in your tests that take too long to track down. Ideally this doesn’t happen, but I have seen it many times.

  1. public class ScannerTest extends TestCase
  2. {
  3. public void testScan()
  4. {
  5. MockControl control = MockControl.createControl(Display.class);
  6. Display mockDisplay = (Display) control.getMock();
  7. Item item = new Item("");
  8. mockDisplay.displayItem(item);
  9. control.replay();
  10. Scanner scanner = new Scanner(mockDisplay);
  11. scanner.scan(item);
  12. control.verify();
  13. }
  14. }

Finally the dynamic mock test was written. This test was the simplest to write as a matter of process also the fewest lines of code. I never needed to leave the scope of the test function. It was just setting up my expectations and letting the test run. As Micah Martin pointed out to me, the test execution seems backwards and unreadable with dynamic mocks. The verification statements are at the beginning of the method and the execution is at the end. This is different than all the other tests in the system that follows an intuitive flow cycle of build, operate, and check.

With a little investigation I found Michael Feathers paper on Self Shunt (www.objectmentor.com/resources/articles/SelfShunPtrn.pdf).

Sentential Testing

by: paul | September 7th, 2006 | 4 comments »

In a project I have been working on, we recently decided to allow wrapped assertions to customize our unit tests. Our purpose was to make the unit tests be sentential enough to explain the meaning of the assertion in the execution of the assertion.

We can’t get rid of all developer comments (variable and method names) because, if we did, we would lose the ability to easily read and, consequently, easily maintain the code. In fact, writing easily readable code is a primary goal of good practices, since it is directly correlated with making code easily maintainable. This is important because maintenance is the most expensive part of the development process. However, we must be cautious about writting comments, since they can often have the opposite effect‚ less maintainable code‚ when they are misrepresentations or plain lies. There is a balance that results in easily read and understood tests. Investing in writing tests to tell a story to the developers who may have to look at the tests in the future, makes maintenance and TDD easier and with a better flow.

We chose to achieve this balance by merging the assertions with the comments of the execution of the test, resulting in a pseudo-sentence. The statement is an explanation for the next developer to read. The form we chose is

Verify.That(positiveAssertionString).ProvedBy(subject).verb(predicate);

An example of one of these assertions is

public void test_PressingBrakesShouldDecelerateVehicle()
{

  1. int originalSpeed = vehicle.currentSpeed;
  2. vehicle.brake();
  3. Verify.That(âš"Brakes decelerate vehicle.").ProvedBy(vehicle.currentSpeed).IsLessThan(originalSpeed);<br>

}

When a developer comes across this story, along with PressingEmergencyBrakeLocksTires(), SlamOnBrakesShouldSkid(), and BrakesShouldAntiLockAtIntervals(), the developer is told a story of what the class is doing. Why do we use custom asserts when good test names will solve the problem?

Changing tests should be cheap. As new designs and behavior evolve in the system, tests are changed to conform to the new structures. When implementing a new design to an existing system (such as breaking up an inheritance in favor of composition), I change the tests to fit the new structure on a macro level. However, this often implies that I am changing the behavior (if only slightly) to please the new design. Yet, test names, like comments, are not executable, so you can‚’t trust them to tell you what the tests test. On a system with heavy refactorings, a test might have its details changed five times without the developer thinking to verify the integrity of the names. An answer is to write sentential explanation of the test as the assert statement since the assert statement executes. I will trust execution over comments every time.

There is a project in its early stages called NSpec(.NET), which is a framework for assertions of a more sentential form. The project is based on the idea of Behavior Driven Development (BDD). RSpec, the same project for ruby has a form of BDD assertions which take full advantage of the features of the dynamic language. It allows you to add the assertion to the object from the test.

For example:
def pressingbrakesshoulddeceleratevehicle
vehicle.brake
vehicle.decelerating?.should_be_true
end

This is really cool! It defines the test as behavior of the object, which it is. However, when the code isn’t ruby, there needs to be other means in place to bind the description of the assertion to something which executes.




Fri, 20 Jan 2006 05:37:12, nraynaud, Tests in a changing world You’re right, we are slowly going to agile world, and for now we have lots of meaningless test taken randomly from existing code (does it makes sense putting a multi megabytes source file in the compiler you test and expecting exactly 2008 errors? without even covering 10% of the compiler). We work on a language, yesterday, I added a restriction to the langugage, it took me 10 minutes to implement and test the change but the rest of the day to change all the others tests.

Moreover, I thank Intellij Idea that renames not only classes but also varialbes named after that class and even comments, this is on the way you takes.



Fri, 20 Jan 2006 13:13:22, David Chelimsky, should_be_decelerating I’ve just submitted a contribution to rspec that will make this even cooler. If vehicle can respond to any of these messages with a boolean value: vehicle.decelerating
vehicle.decelerating?
vehicle.is_decelerating
vehicle.is_decelerating?
then you can write this in your test:
def pressingbrakesshoulddeceleratevehicle
vehicle.brake
vehicle.should_be_decelerating
end
Admittedly, this may be confusing to a programmer who is looking for a “should_be_decelerating” method on vehicle, but the messaging is clear it fails (” should be true”) and it definitely improves the communication of intent. If you’re doing BDD (i.e. spec-first), you’ll get a !-NoMethodError-! on “decelerating”. Then it’s up to you to implement a method responding to any of the forms described above.

Fri, 20 Jan 2006 13:57:32, , How about using Higher Order Messaging style and let the user write:
vehicle.should_be.decelerating?
The test framework could mix should_be and similar higher-order messages into the Kernel module.

Fri, 20 Jan 2006 14:40:41, David Chelimsky, should_be That’s kind of how rspec works now. shouldequal, shouldcontain, shouldbe_true, etc are all mixed in to Object, so you can do things like someobject.someattribute.shouldbetrue. Your suggestion of tying it to a “shouldbe” method (rather than parsing the shouldbe_xxx message) might be more clear. I think, though, that “shouldbe.decelerating?” is weird to read (because of the question mark). Programatically, however, it does make the statement look more like the implementation. I’ll think on it some more…

Over Mocking

by: paul | September 7th, 2006 | 26 comments »

I have noticed using more mocks lately. Instead of using them sparingly for controlling services which are not instrumental to what I am testing, I am essentially using them as a way to isolated what I am testing. This has me noticing a side effect I am not entirely comfortable with. To use the mock, I need to be able to have the mock in the production code, which means I need to inject an abstraction of the mock (dynamic mocks will do that for you).

So, the side effect is long parameter lists, specifically in constructors. Everything takes almost all the objects it uses. Then, to create the production objects are factories. I am using many more factories than I would without mass mocking. I am not sure if this is a good use of dependency decoupling and factory building as design techniques, or if this is a symptom of over design and tightly coupling the mocks to the tests, making it more difficult to change the tests without changing the interface the mock is implementing. Thoughts?

Wed, 24 May 2006 14:03:11, Dave Hoover, Create a default constructor Try poor man’s dependency injection: have a constructor that allows you to inject your dependencies (hidden behind interfaces) for testing, then have a default constructor that instantiates the concrete objects and injects them itself.

Wed, 24 May 2006 15:01:02, David Chelimsky, too many dependencies either way I don’t think mocks or factories are the real problem here. If A depends on the services of B,C,D,E,F,G,H and I, then it’s depending on too many things whether you inject the objects or instantiate them internally.

Wed, 24 May 2006 16:57:06, , Don’t “inject” dependencies. Mock an object’s peers in tests and pass real peers to it’s constructor or as method arguments. Composite objects should create objects they use internally and not expose them at the constructor. A composite object should be simpler than the sum of its parts. Also, avoid passing all dependencies into an object’s constructor: you can probably pass collaborators as method arguments, not constructor arguments.

Wed, 24 May 2006 17:24:56, Dave Hoover, Listen to Chelimsky The smell of a long parameter list leads me to think you may be able to collapse some objects behaind a coarser-grained interface.

Thu, 25 May 2006 11:24:12, Ryan Cooper, DI Containers I find using a DI container like PicoContainer eases the pain by making all (or most of) those factories unnecessary.

I’m still not happy about the long parameter lists in constructors, so I think I will give a few of the suggestions above a try. Thanks all.

Thu, 25 May 2006 16:08:05, Tim Ottinger, The “Airplane” retort “I’ll never be over mocking!”

Fri, 26 May 2006 10:48:42, Asher Sterkin, Over Mocking Personally I mock whatever and whenever I can. Usually a hardship with mocking reveals some interesting deeper design problems. If there are too many arguments for constructor it probably means the class under test has too many dependencies, which means a problem with cohesion. In my experience I seldom need to mock more than 5 interfaces per test case. It’s usually one or two as constructor arguments and two, max three for returned objects. If it’s more I try to re-factor.

Fri, 26 May 2006 16:25:43, Paul Pagel, “In my experience I seldom need to mock more than 5 interfaces per test case.” Do you only mock interfaces?

Sat, 27 May 2006 19:49:22, Rogerio Liesenfeld, I prefer to obtain dependencies with “new” wherever possible In the large (8000+ classes) J2EE web app I am currently working, many business classes obtain instances of other business classes by simply instantiating them with the “new” operator. Besides being the simplest way to obtain dependencies, this allows business service classes to maintain client-specific state, so that private methods don’t need to have any parameters.

Of course, with the mock objects tools previously available, it would have been difficult to unit test such classes. But I wanted to use “new”, and also have final classes, final methods, and static methods where appropriate. So, with that “itch to scratch”, I went ahead and created a new tool that would free me to design the application without constraints, and still have complete unit tests.

If anyone wants to give it a try, the tool is here: jmockit.dev.java.net.

Fri, 9 Jun 2006 10:30:20, Asher Sterkin, Over Mocking “Do you only mock inerfaces?” Not only, but I prefer so. In C++ it really doesn’t matter since there is no good mock library (I use my own which is based on link time substitution; I plan to sourceforge it soon). In Java and C# interfaces do not cost too much, but sometimes you have a class comming from the infrastrucure. You would like to mock it but you do not want to wrap it with an extra interface. For example I recently mocked Java’s TimerTask::cancel in order to validate that in a certain scenario a timer cancellation request is sent properly. I also do test what will my program do if the TimerTask::cancel returns false (too late to cancel).

Fresh Testing

by: paul | September 7th, 2006 | 2 comments »

Sometimes I sit down to write a test on something I haven’t worked on before or don’t know intimately, and I just can’t write the first test. I need a context of the system and a state of existing code. Then I generally do one of two things: look at how things are implemented in the code, or look at other tests that exercise similar behavior. Using either of these as a strict model to write a test is problematic to the flow of TDD.

By using the implementation code as a model, I am limiting one of the great things about TDD from the beginning, the fact the design should evolve as a byproduct of making the test pass. This TDD complacent method tends to ingrain existent design into my mind. These strict models resign to existing design, even if your story/test/problem isn’t exactly the same, just similar enough to convince you of the model.

Copy/pasting a similar test and editing is a developer mistake I commit sometimes when it looks like a freebie is being tossed at me: duplicate then abstract. It is very tempting, yet I have found it painfully regressive. Especially when the tests themselves have begun to rot, as their ability to act as developer docs are deprecated. It causes a lie in logic which is always painful. Either the debugger gets fired up or the test gets scrapped in order to handwrite anyway. Copy/pasting something which is similar is starting from a false expectation most of the time. It is more important to me to have faith in the integrity of my tests.

The most powerful TDD I see is at the beginning of a project, since there is a state of tabula rasa allowing you to move infinitely lateral. Before tests depreciates provides the best model for TDD. Test depreciation is unavoidable, as with design changes, the tests are changed with regularity to accommodate the new structures. The reason for having the tests is to have a safety net to make the code easy to change. It becomes important to keep tests “fresh” when there is already design in place. Otherwise good design appears to degrade due to over/improper use.

Handwriting a test from scratch can seem like an extra step, like reinventing the wheel. Most of the time the extra step is exactly that, an extra step, but in those cases where you are following a false model it is very expensive. It introduces the worst type of design into the system, the kind with little to no smell, but with false premises. Introducing bad design into tests or failing to maintain test code ends up introducing bad design into production code.

COMENTS

Thu, 5 Jan 2006 22:16:48, David Chelimsky, copy/paste Copy/paste can be a real problem, yet it takes an awful lot of discipline to abandon it completely. For example if you’re test driving something new - you write the first test which has some setup in it. You’re not ready to move stuff to a setup method because there’s no duplication to warrant it yet. So for the second test you copy/paste the first test, modify what you will, get it to pass, and then refactor out the duplication. With just a few lines of testing code that’s probably acceptable, but there’s a point where you get yourself in trouble. I guess that’s different for everyone, and perhaps on different days (depending on the coffee/sleep ratio). Maybe committing to a day of absolutely zero copy/paste to see if it really slows me down would be worthwhile.

Thu, 5 Jan 2006 22:53:53, Tim Ottinger, What he said I hate copying from any existing tests, always feeling like I’ve cheated somehow. It is a way to get by (or try to get by) when you don’t really know what you’re doing. When I talk about whether I [[really know][http://tottinge.blogsome.com/2005/12/30/how-can-you-not-know-java/]] something or not, I consider whether I can work from the blank slate. If not, then I don’t really know my topic. Not only is working from tabula rasa liberating, it’s a good indicator that you’ve done enough backgrounding. It’s good on so many levels.

I just wrote the other side of this blog, that [[naive tests don’t help][.ArticleS.TimOttinger.NaiveTestsDontHelp]] so you have to know the software to write tests for new parts. I think that it would be good if we could work on the pro/con of this and give guidance on navigating between sylla and charybdis. If you don’t know enough, you can’t blue-sky the tests. If you are copying the tests, then you only reinforce the implementation in testing (for better or worse). There has got to be a middle way, and some heuristics to help get around: something more useful than “pairing should fix that.”

Fri, 6 Jan 2006 15:50:00, Thomas Eyde, Copy/paste is for professionals – don’t do that at home I think the trick is to write the tests for the truly new requirements, then find reusable code if any, or refactor existing code to be reusable. Not easy, but that’s what I strive for.

I also think there’s nothing wrong to copy/paste and then refactor. It’s without the refactoring things start to get dangerous.

Sat, 7 Jan 2006 12:28:24, Matisse Enzer, Copy and paste as an iterative action Yesterday I was adding tests to some “legacy” code. After I got the library to compile under the test harness I picked one subroutine to test, and create d a test to run that subroutine. Of course I got a run-time exception because the subroutine I was testing made a call to a subroutines defined in some other library. So, I created a stub version of that subroutine in my test harness. ran the test again, another missing external subroutine. I copied and pasted the stub I had created, changed the name, reran the test. Several times. Each time adding a single “fake” subroutine. (Sometimes I had to edit the stubs to return some mock data.)

I also copied-and-pasted my first test. Renamed it, and changed the arguments it passes to the subroutine I’m testing. Did this three times.

Mon, 30 Jan 2006 22:46:53, Paul Pagel, the copy/paste problem There are many ways to introduce code debt into a system. Duplicate code is one of the worse. Copy/Pasting leaves the payment of this debt to the memory of the developer. So if it is copy/paste a few lines at a time, then refactor at the end of small cycles, then I go for it. But if it is going to be coping a file or a series of tests/methods, I won’t.

Beware the Freebie

by: micah | September 7th, 2006 | 0 comments »

The milestones in the life of a story:

  1. Creation: customer creates the story
  2. Estimation: the story is estimated by developers
  3. Selection: the story is selected for an iteration
  4. Specification: tests are written the story
  5. Implementation: the story is implemented to make the tests pass
  6. Acceptance: the customer acknowledges completion of the story after seeing the passing tests and witnessing the new functionality

It is unavoidable. Every story must go through these milestones of life in order. A story cannot be estimated if it has not been created. A story cannot be selected for an iteration if it has not first been estimated. You can attempt to specify a story before it has been selected but you run the risk of being wrong, for the system may change many times before the story is selected. Implementing a story before it has been specified will lead to false implementations. And accepting a story that hasn’t been implemented is just plain silly.

It happens with some frequency, however, that a story gets implemented before it is ever selected, estimated, or perhaps even created. How? A developer may be look at a piece of code and think, “Hey, the customer mentioned he wanted to change this doohickey. I might as well change it now.”. Or a developer may working on one feature and say, “You know, I bet the customer would really like it if I improved this thing-a-magigger”. When this happens, the developer pridefully demonstrates the extra functionality to the customer and says with a smile, “You got a Freebie this iteration!”.

BEWARE THE FREEBIE! A Freebie, by it’s nature, has skipped at least one milestone in it’s life. Most Freebies skip the Selection milestone. This is unfortunate because maybe the customer didn’t really want that story after all. But that’s small potatoes compared to the real danger… Almost all Freebies have skipped the Specification milestone.

Skipping the specification milestone is blasphemous. If a feature has not been specified with tests, how do you know it really works? Worse, how will you know if it still works 2 months from now. Very often Freebies break and nobody knows about it.

I’ve seen it over and over and it’s regrettable every time. A perfectly innocent story is wronged by an overzealous developer. The poor story, out of sync from his peers, strays from the trodden path and becomes a Ghost Story. Becoming a Ghost Story is dreadful fate. They are those stories that were at one time complete, but have since become incomplete. You may never actually see a ghost story but they will surely haunt you. They cause users to have delusions of non-existant functionality and to make exclamations like “Hey! Why doesn’t this stupid app work like it used to?” or “What happened to my favorite feature?”. They keep customers up at night wondering if they actually selected the Ghost Story for an iteration of not. They torment developers forcing them to write code they’ve already written.

Avoid Ghost Stories by avoiding Freebies. Give every story a complete life with all it’s milestones. The next time a developers shows you extra functionality and calls it a Freebie, say “That’s nice. I’ll consider selecting a story for that in a future iteration.”


Mon, 24 Apr 2006 23:17:57, Old Grouch, Another hidded danger By skipping several stages, the freebie runs the risk of breaking something else. An assumption that doesn’t carry throughout the entire system. Usually minor, so it doesn’t show up for months. Then someone else has to rip their hair out. And declare that your parents were never married.

“The more innocuous the change, the greater the ramification.”


Tue, 21 Feb 2006 14:11:34, Gary Dieckman, Looking for Preston and Karen Martin Micah Martin - If your parents are Preston (Tom) and Karen Martin of Proctorville, Ohio, then your dad was best man at my wedding in 1970. I’d like to get in touch. Are you that Micah? gary@exprint.com

Nope, you’ve got the wrong Micah


Tue, 21 Feb 2006 14:11:34, Gary Dieckman, Looking for Preston and Karen Martin Micah Martin - If your parents are Preston (Tom) and Karen Martin of Proctorville, Ohio, then your dad was best man at my wedding in 1970. I’d like to get in touch. Are you that Micah? gary@exprint.com


Thu, 16 Feb 2006 10:09:50, unclebob, Other out of order disfunctions. Indeed! I think you have hit on an interesting way to describe a whole family of dysfunctions. I have certainly seen stories selected before they are estimated. I have seen stories accepted before they are specified. I have seen stories implemented before they are created. Each of these dysfunctions has it’s own particular set of symtoms and ramifications. What are they?


Thu, 16 Feb 2006 08:12:26, chelimsky, skipping selection Well said, Micah. It’s worth noting that 4 of the 6 milestones are customer milestones. As developers, we want to create the best software we create. We talk about it being a team effort (i.e. whole team, customers, developers, et al), but in the end it’s not really our (developers) software. And how can we expect our customer to feel ownership of priorities if we arbitrarily take the their any (sometimes all) of their milestones?