Skip to content

Robot damage example

jimweirich edited this page Sep 11, 2012 · 8 revisions

Robot Damage Example

This annotated example was taken from a programmable robot kata. This spec deals with the damage dealt to a robot when it gets hit with a bullet.

01) require 'spec_helper'
02) require 'botlab/robot_runner'
03)
04) describe RobotRunner do
05)   Given(:runner) { RobotRunner.new }
06) 
07)   Invariant { (runner.energy < 0).should == runner.dead? }
08) 
09)   context "when hit" do
10)     Given!(:original_energy) { runner.energy }
11) 
12)     When(:result) { runner.hit(bullet_energy) }
13) 
14)     Invariant { result.should == bullet_energy }
15)     Invariant { runner.energy.should == original_energy - bullet_energy }
16) 
17)     context "lightly" do
18)       Given(:bullet_energy) { 5 }
19)       Then { runner.should_not be_dead }
20)     end
21) 
22)     context "pretty hard" do
23)       Given(:bullet_energy) { original_energy }
24)       Then { runner.should_not be_dead }
25)     end
26) 
27)     context "really hard" do
28)       Given(:bullet_energy) { original_energy + 1 }
29)       Then { runner.should be_dead }
30)     end
31)   end
32) end

Annotations

Line 5: The robot runner is responsible for interfacing the Robot AI (not shown here for brevity) and the robot simulation framework. Here we create a single runner for testing.

Line 7: The robot runner defines a boolean method named "dead?" that should be true whenever the energy level drops below zero. By specifying that the two are equivalent here in an invariant, we hold that this relationship between energy_level and dead? should hold true for all the scenarios in this specification.

Line 9: The following specification applies when a robot is hit by a bullet.

Line 10: We're going to compare the change in runner energy with the original value, so we grab the original value here with a non-lazy Given!. This captures the energy level before the When clause is run.

Line 12: This is the code under test. All the assertions in this context (and child contexts) should be centered on verifying this code.

Line 14: Specify that in all scenarios covered by this invariant, the result of the hit call (in the When clause) will be the amount of the bullet energy.

Line 15: Specify that in all scenarios covered by this invariant, the energy of the robot will be reduced by the amount of energy in the bullet.

Line 17: In the first nested scenario, we are going to explore what happens when the robot is hit lightly by the bullet.

Line 18: Specify that the bullet energy in this scenario is only 5 points. Notice at this point we finally define a given that is assumed in line 11.

Line 19: With that amount of energy, the robot will not be dead. At this point, all three invariants in scope (from lines 7, 15 and 16) are checked as well. This makes sure the dead method and energy methods are in sync, the robots energy level is appropriately changed, and the the result of the hit method is correct.

Line 22-25: Another nested scenario, this time exploring what happens when the robots energy level is reduced to zero. All the invariants apply here as well.

Lines 27-30: The final scenario where we explore reducing the robots energy to below zero. Again, the invariants are applied here.