# Getting started with RSpec — Part 2

Note: This is the second and final installment of the RSpec — Getting Started series. If you haven’t read the first part, please go back (link) and read it before continuing.

In the previous edition of “Getting Started with RSpec” we made a simple calculator with unit tests. We saw how tests can help us maintain code even when working with pretty dumb programmers.

In this installment we are going to be focusing on Test Driven Development (TDD). What is TTD?

Test Driven Development is the workflow of writing a test, letting it fail, and then changing your code to make it (and all the previous tests) pass.

Enough talk, let’s get coding

To demonstrate let’s add a `subtract`

method to our calculator. To do this following a TDD workflow, we first add a test with our expectations:

# File: spec/calculator_spec.rbrequire './calculator.rb'describe "calculator" doit 'adds numbers' do

...

endit 'subtracts numbers' do

calc = Calculator.new

expect(calc.subract(5,1)).to eql(4)

endend

This new `subtracts numbers`

test is expecting that when we call the `subtract`

function and pass it two parameters, `5`

and `1`

we will be returned a value of `4`

Let’s run the tests to make sure we don’t have any syntax errors:

calculator $ bundle exec rspec

.FFailures:1) calculator subtracts numbers

Failure/Error: expect(calc.subtract(5,1)).to eql(4)

NoMethodError:

undefined method `subtract' for #<Calculator:0x007f9dc4a65f40>

# ./spec/calculator_spec.rb:11:in `block (2 levels) in <top (required)>'Finished in 0.00236 seconds (files took 0.08835 seconds to load)

2 examples, 1 failureFailed examples:rspec ./spec/calculator_spec.rb:9 # calculator subtracts numbers

Just what we expected. One of our tests has failed. We can see which test has failed in the last line of the output.

Now that we have written our test and have seen it fail, it’s time to make it pass.

Let’s create a subtract method in our Calculator:

# File: calculator.rbclass Calculator

def add(x, y)

x + y

end

def subtract(x, y)

x - y

end

end

The last step in TDD is to make all the tests pass. This is sometimes called going “Green,” since the output of passing tests is green. To see if our Calculator behaves as we want it to, run the tests:

calculator $ rspec

..Finished in 0.00224 seconds (files took 0.08993 seconds to load)

2 examples, 0 failures

Perfect! You’ve just completed your first TDD cycle! That wasn’t too difficult, was it?

Now that you’re feeling confidant in your abilities, let’s repeat this process for the`multiply`

and `divide`

functions. Let’s start with `multiply`

:

# File: spec/calculator_spec.rbrequire './calculator.rb'describe 'calculator' do

it 'adds numbers' do

...

endit 'subtracts numbers' do

...

endit 'multiplies numbers' do

calc = Calculator.new

expect(calc.multiply(3,4)).to eql(12)

endend

Make sure your tests fail by running `rspec`

Then change your code so your tests pass:

# File: calculator.rbclass Calculator

def add(x, y)

x + y

enddef subtract(x, y)

x - y

enddef multiply(x, y)

x*y

endend

Do your tests now pass?

calculator $ rspec

...Finished in 0.00262 seconds (files took 0.08638 seconds to load)

3 examples, 0 failures

Lookin’ good! Lastly let’s finish with our `divide`

function:

# File: spec/calculator_spec.rbrequire './calculator.rb'describe 'calculator' do

it 'adds numbers' do

...

endit 'subtracts numbers' do

...

endit 'multiplies numbers' do

...

endit 'divides numbers' do

calc = Calculator.new

expect(calc.divide(5,2)).to eql(2.5)

endend

Watch your test fail and then add the `divide`

method:

# File: calculator.rbclass Calculator

def add(x, y)

x + y

enddef subtract(x, y)

x - y

enddef multiply(x, y)

x*y

enddef divide(x, y)

x / y

end

end

One final check gives us:

calculator $ rspec

...FFailures:1) calculator divides numbers

Failure/Error: expect(calc.divide(5,2)).to eql(2.5)

NoMethodError:

undefined method `divide' for #<Calculator:0x007fc9c0345440>

# ./spec/calculator_spec.rb:23:in `block (2 levels) in <top (required)>'Finished in 0.00278 seconds (files took 0.09446 seconds to load)

4 examples, 1 failureFailed examples:rspec ./spec/calculator_spec.rb:21 # calculator divides numbers

Whoops! That’s clearly not right. We were expecting all our tests to pass. What’s going on here?

To get more information about the error, we can add a handy feature of RSpec, output formatting. In the console run the command `rspec --format documentation`

and you should get this:

calculator $ rspec

...FFailures:1) calculator divides numbers

Failure/Error: expect(calc.divide(5,2)).to eql(2.5)

expected: 2.5

got: 2

(compared using eql?)

# ./spec/calculator_spec.rb:23:in `block (2 levels) in <top (required)>'Finished in 0.01352 seconds (files took 0.09081 seconds to load)

4 examples, 1 failureFailed examples:rspec ./spec/calculator_spec.rb:21 # calculator divides numbers

We were expecting the value `2.5`

to be returned, but instead we received a value of `2`

This is where TDD really shines bright. If we hadn’t had these tests in place, we would have been in trouble when we needed to use the divide function in production.

To fix this problem, we need to change one the `divde`

inputs to `Float`

with the `.to_f`

function:

`def divide(x, y)`

x / y.to_f

end

Now that we’ve made a change, we rerun the tests:

calculator $ rspec

....Finished in 0.00271 seconds (files took 0.09715 seconds to load)

4 examples, 0 failures

That’s better. Now that all of our tests are passing, we can call it a day. Great work!

Test Driven Development is an important tool in any developer’s toolbox. It allows us to develop with the confidence that our code is not going to break if we change something. It’s especially helpful when refactoring our code to ensure that all the functions work properly. Refactoring is almost impossible without test to back it up. If you have any questions about TDD please feel free to leave a comment below