Table of contents

Today we will learn how to test our Ruby code using a tool called RSpec.

What is RSpec?

RSpec is a test framework for Ruby. RSpec is like a helpful robot assistant. You tell it what your code should do, and it checks if your code actually does that. It's a way to make sure your program behaves the way you expect it to.
Install: $ gem install rspec # for rspec-core, rspec-expectations, rspec-mocks

A simple example
Let’s say we have a simple calculator program.

# calculator.rb
class Calculator
  def add(a, b)
    a + b
  end
end

How do you know it's working correctly? You'd probably try adding some numbers and see if you get the right answer. That's exactly what testing is all about - but we're letting the computer do the checking for us!
RSpec uses the words "describe" and "it" so we can express concepts like a conversation:

"Describe a Calculator."
"It correctly adds two numbers."

Don't worry about remembering exact commands or syntax - let's focus on the big picture!

Here is how we can use RSpec for testing. We call the add method with 2 and 3. We expect the result to equal 5.

# calculator_spec.rb
require_relative 'calculator'

RSpec.describe Calculator do
  describe '#add' do
    it 'correctly adds two numbers' do
      calc = Calculator.new
      result = calc.add(2, 3)
      expect(result).to eq(5)
    end
  end
end

To run this test, you would type $ rspec calculator_spec.rb in your terminal. If everything is working correctly, you'll see a green dot, indicating that the test passed!

RSpec Expectations and RSpec::Matchers

RSpec::Expectations provides a simple, readable API to express the expected outcomes in a code example. To express an expected outcome, wrap an object or block in expect, call to or to_not (aliased as not_to) and pass it a matcher object. Read more https://rspec.info/documentation/3.13/rspec-expectations/RSpec/Expectations.html
RSpec::Matchers provides a number of useful matchers we use to define expectations. Any object that implements the matcher protocol can be used as a matcher. Read more https://rspec.info/documentation/3.13/rspec-expectations/RSpec/Matchers.html

Testing Different Scenarios

When we test our calculator's addition function, we want to make sure it works in all sorts of situations. Here are some ideas of what we might want to check:

  1. Does it correctly add two positive numbers?
  2. What about a positive and a negative number?
  3. How about two negative numbers?
  4. Does it handle zero correctly?
  5. Can it deal with decimal numbers?
  6. What happens with really big numbers?

Here's an enhanced version of the RSpec code:

# calculator_spec.rb
require_relative 'calculator'

RSpec.describe Calculator do
  let(:calculator) { Calculator.new }

  describe '#add' do
    it 'correctly adds two positive numbers' do
      expect(calculator.add(2, 3)).to eq(5)
    end

    it 'correctly adds a positive and a negative number' do
      expect(calculator.add(5, -3)).to eq(2)
    end

    it 'correctly adds two negative numbers' do
      expect(calculator.add(-2, -3)).to eq(-5)
    end

    it 'returns zero when adding zero to zero' do
      expect(calculator.add(0, 0)).to eq(0)
    end

    it 'returns the same number when adding zero' do
      expect(calculator.add(7, 0)).to eq(7)
      expect(calculator.add(0, 7)).to eq(7)
    end

    it 'correctly adds decimal numbers' do
      expect(calculator.add(1.5, 2.7)).to be_within(0.01).of(4.2)
    end

    it 'correctly adds large numbers' do
      expect(calculator.add(1000000, 2000000)).to eq(3000000)
    end
  end
end

By including these additional tests, we're ensuring that our add method works correctly for a wide range of inputs. This is called "edge case testing" - we're not just testing the obvious cases, but also the less common or potentially problematic ones.
To run these tests, you would still use the command rspec calculator_spec.rb in your terminal. If all tests pass, you'll see a series of green dots, one for each test. If any test fails, you'll see a red F instead of a green dot, along with information about what went wrong.

The Testing Mindset

When you're writing tests, try to think like a detective. What are all the ways your code might be used? What could go wrong? By anticipating these scenarios, you can write better tests and, as a result, better code.
As your programs get bigger and more complex, it's easy for new changes to accidentally break something else. Tests help catch these problems early.

Greetings! Thank you for reading an article titled Write Reliable Ruby Code with RSpec Testing which has been authored by Le Huan Vu. In case you wish to gather more insights about the author, you may consider visiting .