You don't have to rewrite the world. You just have to be able to fool your tests about the state of the world (in this case, time). The usual way to control time in tests is to stub.
I would write that scenario like this
Scenario: Take damage when I stand in lava.
Given I have 10 health
And there is a block of lava next to me
When I note the time
And I step in to the block of lava
And I wait 5 seconds
Then I should have 8 health
and implement the time steps like this:
When /^I note the time$/ do
@start = Time.now
end
When /^I wait (\d+) seconds$/ do
Time.stub(:now) { @start + 5.seconds }
end
When I note the time
is kind of artificial, so you might fold that in to another step if it made sense. (I don't see an appropriate step in this case, but you might in a longer scenario.) When I wait 5 seconds
is perfectly appropriate to the domain, though.
Other niceties:
- It's concise and appropriate to the domain to use first person.
Given
is for conditions that are true before the scenario starts. One way to think about it is that time might have elapsed between when theGiven
becomes true and when the actual scenario starts, during which other things might have happened that aren't relevant to the scenario.- Health doesn't have much to do with standing next to lava, so those are better set up in separate steps.
- Testing that you've taken two damage (as opposed to that your health is 8) would require a dependency between the assertion step and the
Given
that initializes your health. Minimizing such dependencies makes Cucumber steps more reusable. So as long as it doesn't hurt understandability (which I don't think it does in this case) just assert the final state at the end.