Skip to content

Tutorial: inherited when

jimweirich edited this page Sep 4, 2012 · 10 revisions

This is part of the RSpec/Given Tutorial

Inherited When

Our previous spec (on page Tutorial: Immediate Given) only handles a single condition of the requirements, when the attack succeeds. There is also the case of the critical hit (explicitly called out in the story) and the case of the miss (implied by the story).

Let's add them to our spec using nested context blocks.

describe "Character can be damaged" do
  Given(:attacker) { Character.new("Attacker") }
  Given(:defender) { Character.new("Defender") }
  Given!(:original_hp) { defender.hit_points }

  Given(:losing_dice_roll) { 2 }
  Given(:winning_dice_roll) { 19 }
  Given(:critical_dice_roll) { 20 }

  context "when the attacker misses" do
    When { attacker.attack(defender, losing_dice_roll) }
    Then { defender.hit_points.should == original_hp }
  end

  context "when the attacker hits" do
    When { attacker.attack(defender, winning_dice_roll) }
    Then { defender.hit_points.should == original_hp - 1 }
  end

  context "when the attacker gets a critical hit" do
    When { attacker.attack(defender, critical_dice_roll) }
    Then { defender.hit_points.should == original_hp - 2 }
  end
end

Notice how we take advantage of Givens defined in the outer scope in each of the inner scopes. This is a good technique.

Also notice how each of the nested contexts are just a minor variation on the basic test. We change the dice roll and we have a different effect on the change in hit points. However, we have to carefully examine each of the contexts to make sure that is the only change between the contexts. It would be nice if we could make variations stand out a bit more.

Refactoring the Common Actions from the Contexts

describe "Character can be damaged" do
  Given(:attacker) { Character.new("Attacker") }
  Given(:defender) { Character.new("Defender") }
  Given!(:original_hp) { defender.hit_points }

  Given(:losing_dice_roll) { 2 }
  Given(:winning_dice_roll) { 19 }
  Given(:critical_dice_roll) { 20 }

  Given(:change_in_hp) { defenders.hit_points - original_hp }
  When { attacker.attack(defender, dice_value) }

  context "when the attacker misses" do
    Given(:dice_value) { losing_dice_value }
    Then { change_in_hp.should == 0 }
  end

  context "when the attacker hits" do
    Given(:dice_value) { losing_dice_value }
    Then { change_in_hp.should == -1 }
  end

  context "when the attacker gets a critical hit" do
    Given(:dice_value) { losing_dice_value }
    Then { change_in_hp.should == -2 }
  end
end

--

Tutorial: Immediate Given

Previous: Tutorial: Immediate Given