RSpec WTF

Fri Apr 23 2021

As I mentioned in my previous post, RSpec is a wonderful tool for learning Test-Driven Development (TDD). It should be noted that on RSpec's website, it refers to itself as a Behavior-Driven Development (BDD) tool. The difference between these two terms is slight, so for the purpose of this post, treat both as the same, and I will refer to both as TDD/BDD.

The first thing to know about RSpec is that it is a Ruby gem, so if you are using a different language, there are most likely multiple options for testing your specific language, but the principles should be the same. Because RSpec is a gem, it can be installed by simply running gem install rspec in your terminal or by adding gem 'rspec' to your project's Gemfile, then running bundle install.

Once RSpec is installed, it's time to write your tests, or specs as RSpec calls them. These are usually stored in a specs folder in the root of your project. Split your specs up by functional area, and be sure that each spec filename ends with _spec. Don't worry; we'll go through a simple example now:

  1. Create a new folder called rspec_example. Inside it, create a file called example.rb and a file called example_spec.rb.

  2. In example_spec.rb type the following:

    require 'rspec'

    require_relative './example'

    RSpec.describe 'example' do
      it "returns 'Hello, World!'" do
        expect(hello_world()).to eq('Hello, World!')
      end
    end

    What this means should be fairly self-explanatory, as RSpec is designed to almost mirror normal speech. The eq stands for 'equal' and uses the == operator to compare the result of the method called inside expect(hello_world()) with the value inside eq('Hello, World!'). If they are equal, the spec passes, and if not it fails.

  3. Save and run rspec example_spec.rb from your console. It should fail with an error message: NoMethodError: undefined method 'hello_world' for #<RSpec::ExampleGroups::Example:0x00000000022ae188> or something like it. This is good. This is saying that we have no method hello_world in example.rb, which we don't because we haven't created it. Let's do that now.

  4. In example.rb create a method hello_world like so:

    def hello_world
    end

    Don't worry about having it do anything yet. Just save and run rspec example_spec.rb again. Now we see this message:

    F
    Failures:
      1) example returns 'Hello, World!'
        Failure/Error: expect(hello_world()).to eq('Hello, World!')
          expected: "Hello, World!"
            got: nil
          (compared using ==)
        # ./example_spec.rb:6:in `block (2 levels) in <top (required)>'
    Finished in 0.18145 seconds (files took 0.07452 seconds to load)
    1 example, 1 failure
    Failed examples:
    rspec ./example_spec.rb:5 # example returns 'Hello, World!'

    This actually tells you a lot. The red F at the top tells you that one spec failed. We only wrote one spec, but if you had more, there would be a red F for each failure and a green . for each pass. The information after the 1) tells you which spec failed, what was expected and what was actually received by theexpectin our spec. We see that it expected to receive 'Hello, World!' but actually received nil. We aren't returning anything from our method yet, so that makes sense. We need to write more.

  5. Back in example.rb change hello_world to match the following:

    def hello_world
      'Hello, World!'
    end

    Then save and run rspec example_spec.rb one more time.

    A green dot! And look, zero failures!

Congratulations! You have written your first test using RSpec, and written it in a TDD/BDD way. Now go, read the docs and expand your ability to use this wonderful tool for your own projects.

Happy coding!