49 Days of Ruby: Day 47 -- Testing Frameworks: RSpec
Tags: ruby
Published: 2021-05-13 05:47:41

---
title: 49 Days of Ruby: Day 47 -- Testing Frameworks: RSpec
published: true
description: Join us on a 49 day learning journey through Ruby!
series: 49 Days of Ruby
tags: #ruby
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9m73qaetuse3nm3y3it8.png
---

**Welcome to day 47 of the 49 Days of Ruby! 🎉**

Yesterday, we explored the testing library Minitest as we looked at testing implementations in Ruby for the first time.

Today, we are going to explore RSpec as another testing framework option. RSpec has a lot of "bells and whistles", which can be overwhelming, and you may not need all of them all the time. However, when you do need one of those bells or whistles, you will appreciate the benefits of it being packaged together.

[RSpec](https://github.com/rspec/rspec) defines itself as:

> Behavior driven development for Ruby

Essentially, RSpec when done within a context of TDD (Test Driven Development), trains the developer to think about the kind of results they want their code to accomplish. It is done using maximally human readable language.

For example, this is what a test in RSpec might look like, taken from the [RSpec website](https://rspec.info/):

```ruby
RSpec.describe Bowling, "#score" do
  context "with no strikes or spares" do
    it "sums the pin count for each roll" do
      bowling = Bowling.new
      20.times { bowling.hit(4) }
      expect(bowling.score).to eq 80
    end
  end
end
```

Do you notice how verbose that example is? There are keywords like `describe`, `context`, and `it`. All those statements help form a clear human sentence when the test is run:

```bash
$ bin/rspec 

Bowling#score
  with no strikes or spares
    sums the pin count for each roll 

Finished in 0.00137 seconds (files took 0.13421 seconds to load)
1 example, 0 failures
```

You do not need to have the `context` block, but it helps add another layer of comprehensibility to a test when running it. 

## RSpec Basics

Let's cover a little bit of the basic functionality of RSpec. I encourage you to spend some time today familiarizing yourself more with it and see what kind of tests you can build!

Imagine we had some code in a file called `my_code.rb` and we wanted to test it.

First, we would `require` that file in our test file. The convention is to name the test file the same name as the code file and append `_spec` to it: `my_code_spec.rb`:

```ruby
# my_code_spec.rb

require "my_code"
```

Now, let's continue our imagined example and say we had a class called `Coffee` inside our `my_code` file:

```ruby
# my_code_spec.rb

require "my_code"

RSpec.describe Coffee do
end
```

Then, now extending it, we also have a class method called `#name`:

```ruby
# my_code_spec.rb

require "my_code"

RSpec.describe Coffee do
  context "when asked for a coffee name" do
    it "returns the correct name" do
      expect(Coffee.name).to eq("Espresso")
    end
  end
end
```

That is a pretty straightforward test. We want to confirm that when the `#name` method is invoked that it outputs the string `Espresso`.

What if our `Coffee` class was a bit more complex and had a lot of parameters to initialize with? Would we have to make a new instance for each test? The `subject` convention can help make that less repetitive. Perhaps the `#name` method is actually an instance method:

```ruby
# my_code_spec.rb

require "my_code"

RSpec.describe Coffee do
  let(:subject) do
    Coffee.new(
      something: "its value",
      something_else: "its value",
      another_thing: 123456,
      yet_another_thing: true,
      coffee_type: "Espresso"
    )
  end

  describe "#name" do
    it "returns the correct coffee name" do
      expect(subject.name).to eq("Espresso")
    end
  end
end
```

We can continue to reuse that `subject` variable, which holds an instance of `Coffee` for all of our relevant tests. It can save us a lot of repetitive typing!

For the rest of the day continue exploring RSpec. Try to write some tests that define your future code's expectations, and then write the code to help those tests pass.

See you tomorrow!

**Come back tomorrow for the next installment of 49 Days of Ruby! You can join the conversation on Twitter with the hashtag [#49daysofruby](https://twitter.com/hashtag/49daysofruby).**