context "A stack with one item" do setup do @stack = Stack.new @stack.push "one item" end specify "should return top when you send it 'top'" do @stack.top.should_equal "one item" end end Run the spec...
$ spec stack_spec.rb -v

An empty stack
- should keep its mouth shut when you send it 'push'

A stack with one item
- should return top when you send it 'top' (FAILED - 1)


1)
NoMethodError in 'A stack with one item should return top when you send it 'top''
undefined method `top' for #
./stack_spec.rb:35:in `should return top when you send it 'top''

Finished in 0.000677 seconds

2 contexts, 2 specifications, 1 failure
Again, running the spec tells us what we have to implement next. undefined method `top' for # tells us to implement a top method. So, back in stack.rb... def top end Why not implement the return now? Well, this becomes a matter of taste and level of discipline. While you're learning BDD (especially if you have no prior TDD experience), you want to take very, very small steps. There's usually something to learn after each one. In this case, if we run the spec now...
$ spec stack_spec.rb -v

An empty stack
- should keep its mouth shut when you send it 'push'

A stack with one item
- should return top when you send it 'top' (FAILED - 1)


1)
ExpectationNotMetError in 'A stack with one item should return top when you send it 'top''
nil should equal "one item"
./stack_spec.rb:35:in `should return top when you send it 'top''

Finished in 0.000531 seconds

2 contexts, 2 specifications, 1 failure
This is a very interesting result. nil should equal "one item" tells us that the expression @stack.top returned nil. In ruby, nil is a real object to which you can send messages. should_equal "one item" tells rspec that the object returned by the expression (in this case nil) should be equal to the string literal "one item". So let's get the code to meet this specification. When we do this, we want to implement the simplest thing that we can to satisfy the existing specs. Given the current set of specs, we can simply return "one item" class Stack def push item end def top "one item" end end Run the specs...
$ spec stack_spec.rb -v

An empty stack
- should keep its mouth shut when you send it 'push'

A stack with one item
- should return top when you send it 'top'


Finished in 0.0004 seconds

2 contexts, 2 specifications, 0 failures
Seems odd? We know that we don't want to always return "one item", so the implementation seems silly. But that implementation did something great. It made it so all of our expectations are met and we didn't have to change much to get there. We always want to take really small steps, with all the specs passing between each step. Now that we have passing specs, we're free to refactor - and we WANT to refactor because we've introduced duplication between the specs and the implementation. So let's refactor to eliminate this duplication. We can use the existing push method to setup the item that top will return. class Stack def push item @item = item end def top @item end end So now we have two specifications, each with their own context. We've implemented two simple methods that satisfy the existing specifications. If you've never done any TDD before this, this may seem really odd. We all know that this isn't enough to meet the specs that we intend. But right now, at this moment, as far as the code is concerned, there are only two simple specifications. To move our implementation along, we first have to specify more about how we want our stack to behave. Previous | Next OK. That's pretty standard stuff so far, but it's all about the object's state, not its behaviour. We want to think about what our Stack does - how it responds to various messages that we can send it. What should an empty Stack do when you send it the push method? Absolutely nothing, right? It should just accept the object and keep its mouth shut: context "An empty stack" do ... specify "should keep its mouth shut when you send it 'push'" do end end
$ spec stack_spec.rb -f s

A new stack
- should be empty

An empty stack
- should not be empty after 'push'
- should keep its mouth shut when you send it 'push'

Finished in 0.000552 seconds

2 contexts, 3 specifications, 0 failures
Actually, I'd like the "keep its mouth shut" spec to come first - I think it reads better. So let's just switch them around in the context: context "An empty stack" do setup do @stack = Stack.new end specify "should keep its mouth shut when you send it 'push'" do end specify "should not be empty after 'push'" do @stack.push 37 @stack.should_not_be_empty end end
$ spec stack_spec.rb -f s

A new stack
- should be empty

An empty stack
- should keep its mouth shut when you send it 'push'
- should not be empty after 'push'

Finished in 0.000557 seconds

2 contexts, 3 specifications, 0 failures
RSpec reads the contexts and specs within a given file in the order in which they appear, giving you some control over this output. So what can we expect here? The name of the spec tells us - "should keep its mouth shut". That implies that it should not react in any way - including raising an error. So let's set the expectation that there will be no error raised: specify "should keep its mouth shut when you send it 'push'" do lambda { @stack.push Object.new }.should_not_raise end If you're not familiar, lambda accepts a block but does not execute it. It then constructs a Proc object, which can called at any time. So, in this case, the block { stack.push Object.new } gets saved in a Proc object. should_not_raise then tells rSpec to call the Proc and raise an ExpectationNotMetError if it raises any errors at all. Running the spec...
$ spec stack_spec.rb -v

An empty stack
- should keep its mouth shut when you send it 'push' (FAILED - 1)


1)
ExpectationNotMetError in 'An empty stack should keep its mouth shut when you send it 'push''
 should not raise  but raised #>
./stack_spec.rb:10:in `should keep its mouth shut when you send it 'push''

Finished in 0.000418 seconds

1 context, 1 specification, 1 failure
The first line tells us the rSpec error that was raised: we were expecting that nothing would be raised, but something (anything) was, so we get an "ExpectationNotMetError". The second line tells us that we specified that there should be no Exception (in this case we didn't specify what type of exception, so by default rSpec assumes Exception), but that there was a NoMethodError raised. The third line tells us that the error was raised in the block defining the specification "should keep its mouth shut when you send it 'push'". We get a NoMethodError because our stack doesn't know what to do with the "push" message. So we add it... class Stack def push item end end ...and run the spec and voila!...
$ spec stack_spec.rb -v

An empty stack
- should keep its mouth shut when you send it 'push'


Finished in 0.000209 seconds

1 context, 1 specification, 0 failures
... the code meets the first specification. Now obviously this code doesn't do much, but that's because we have more specifications to write! One important thing to note here is that we did not begin by setting any expectations about the size or emptiness of the stack. That may feel funny to experienced TDDers, as it is standard faire to verify that an empty collection is empty. As explained in the Overview, we're going to explore what it means to specify behaviour rather than testing state. Based on our existing spec thus far, there is no need to have a size or empty method. Let's see how far we can go without them...