Twitter

Test-Driven Development in Ruby: Using RSpec For Feature & Unit Tests

RSpec is a framework used in test-driven development (TDD) for writing feature and unit tests to evaluate whether a computer program is fit for purpose.

Test-Driven Development works in a red-green loop:

The test always fails the first time because when we write the test, we haven’t attempted to pass it yet.

RSpec can be installed by navigating to the root project folder and typing:

$ gem install rspec

Feature & Unit Tests

Unit tests test individual parts of the logic of a program. When you write a unit test, it should be as small and simple as possible. A feature test tests the program as a user. e.g. using the interface a user would use to see if the feature works.

Guide To RSpec

By convention, tests written with RSpec are called “specs” (short for “specifications”) and are stored in the project’s spec directory at root/spec/.

With RSpec, we are always describing the behaviour of classes, modules and their methods. The describe block is always used at the top to put specs in a context. It can accept either a class name, in which case the class needs to exist, or any string you’d like.

describe ClassName do
end

This is perhaps the simplest RSpec test. This test will simply test for the existence of ClassName.

If we run the test now, it will fail because we haven’t written any code yet. This is in fact what we expect, so it’s not a bad thing.

We will get a uninitialized constant error because we have asked the test to check for the existence of a constant called ClassName, but as we have no production code yet, this constant cannot possibly exist – because nothing exists yet.

All we have to do to get this test to pass is to initialise the constant by calling it in the production code (stored by convention in the lib folder):

class ClassName
end

Before we run the test again, we need to alert Rspec of the existence of the file in which we’ve called the constant.

At the top of the spec file (above the test), add the line:

require 'filename'

Note: the file extension (.rb) and the relative file path (root/lib/) are assumed by Rspec.

The test should now pass.

More Tests…

Let’s look at a slightly more complex example…

describe StringCalculator do

  describe ".add" do
    context "given an empty string" do
      it "returns zero" do
        expect(StringCalculator.add("")).to eq(0)
      end
    end
  end
end

Notes about this example:

RSpec Test Template

describe ClassName do
  describe "methodname" do
    expect(Classname.methodname($args)).to eq(result)
  end
end

RSpec One-Liner Syntax

Rspec tests can also be written using one-liner syntax. There is surprisingly little literature about this online.

I need to figure this out.

to complete

Copyright 2021. All Rights Reserved. Adam Patel