Ruby Testing Micro-Course, Lesson 1

by Jason Swett,

Lesson 1 / Lesson 2 / Lesson 3 / Lesson 4

What We’re Going to Do in This Micro-Course

This micro-course is just Ruby and RSpec. No Rails, no database, no HTML.

We’re going to build a Ruby application designed for the purpose of managing a hotel. We’ll build this application over the course of four easy-to-follow lessons.

Lesson 1 Overview

First I’m going to show you a super tiny version of the application we’re going to build. We’re going to examine this tiny “codebase” together and make sure we understand exactly how it works.

The app includes one test that I’ve written. You’ll run the test on your machine. You’ll modify the app so the test breaks, then you’ll fix the app again.

Finally, you’ll add a tiny feature to the app as well as a test for it. Then you can compare your test to the test I wrote so you can see how you did.

Here we go!

The “Codebase”

Here’s the program we’ll be starting with. Don’t worry if you don’t understand 100% of it right now. We’ll be examining this program in detail to make sure there are no mysteries by the time we’re done.

require 'rspec'

class Hotel
  attr_accessor :guests

  def initialize
    @guests = []
  end

  def check_in_guest(guest_name)
    @guests << guest_name
  end
end

describe Hotel do
  it 'can check in a guest' do
    hotel = Hotel.new
    hotel.check_in_guest('George Harrison')
    expect(hotel.guests).to include 'George Harrison'
  end
end

Let’s take a closer look at this code, starting with the test.

First Test: Checking In a Guest

Here’s the single test that I’ve included in this program:

hotel = Hotel.new
hotel.check_in_guest('George Harrison')
expect(hotel.guests).to include 'George Harrison'

You can probably intuit what this test is doing even if you’re a newcomer to Ruby and/or testing. If we were to translate this test to English, we might say, “When I check George Harrison into a hotel, I expect that hotel’s guests to include George Harrison.”

Let’s actually run the test.

Running the Test

If you don’t already have RSpec installed, do so now by running gem install rspec.

We can run our test by running the rspec command and specifying the name of our test file.

$ rspec hotelier_spec.rb 
.

Finished in 0.00542 seconds (files took 0.12365 seconds to load)
1 example, 0 failures

The test should pass. But there’s a problem.

How do we know that our test is really testing something? Our test could be passing because our code works, or our test could be passing because we made a mistake in the test.

The only way we can be sure is to intentionally make the test fail, then make it pass again.

Making the Test Fail

Let’s modify our code in some way such that it will no longer make the test pass. If we comment out the body of `check_in_guest`, that should do it.

require 'rspec'

class Hotel
  attr_accessor :guests

  def initialize
    @guests = []
  end

  def check_in_guest(guest_name)
    #@guests << guest_name
  end
end

describe Hotel do
  it 'can check in a guest' do
    hotel = Hotel.new
    hotel.check_in_guest('George Harrison')
    expect(hotel.guests).to include 'George Harrison'
  end
end

Let’s run our test file again to verify that the test fails now.

$ rspec hotelier_spec.rb 
F

Failures:

  1) Hotel can check in a guest
     Failure/Error: expect(hotel.guests).to include 'George Harrison'
       expected [] to include "George Harrison"
     # ./hotelier_spec.rb:19:in `block (2 levels) in <top (required)>'

Finished in 0.01585 seconds (files took 0.0873 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./hotelier_spec.rb:16 # Hotel can check in a guest

The test does in fact fail. We can now be sure that our test is testing what we think it’s testing.

Before you move on, uncomment the body of check_in_guest and run the test file again to make sure that we’re back in a working state.

Exercise: Write Your Own Test

Now that you’ve seen me write a test, I want you to write your own test.

Here’s your exercise: write a test that will check a guest out. Let’s verify that when we check someone in and then check him or her out, the hotel no longer lists that person among its guests.

Here’s the code you can use as a starting point. I added an `it` block for you to put your test inside of.

require 'rspec'

class Hotel
  attr_accessor :guests

  def initialize
    @guests = []
  end

  def check_in_guest(guest_name)
    @guests << guest_name
  end
end

describe Hotel do
  it 'can check a guest in' do
    hotel = Hotel.new
    hotel.check_in_guest('George Harrison')
    expect(hotel.guests).to include 'George Harrison'
  end

  it 'can check a guest out' do
    # Put your own test here
  end
end

When you’re finished, move onto Lesson 2. In Lesson 2 I’ll show you my version of the test. You can compare your work to mine and see how similar or different it is.

By the way, if you’re drawing a total blank, that’s okay. Just move onto the next lesson to see how I wrote the test. You’ll have more opportunities to try writing tests later in the micro-course.

Continue to Lesson 2 >>>

7 thoughts on “Ruby Testing Micro-Course, Lesson 1

  1. Axel

    Thanks for this write up! I have successfully run a rspec test for the first time after following this post.
    I followed other tutorials before but got stuck when they introduced factory/controller spec etc then gave up testing altogether πŸ˜…

    Reply
  2. Vignesh

    Jason, it was exciting having had an opportunity to go through this lesson with you. Jason has tutor gene, has passion for teaching code. Instructions are very clear, effective and straightforward. Keeping student’s current level of their experience in mind, you gently advance towards understanding the code that one is writing.

    Reply
  3. kailoon

    Thanks for the mini course, I am new to RoR development and struggle with testing. Finished the Rails 5 book and test prescription, but, most of the time I have no idea what’s that or I am like wondering in the forest…

    Let’s go lesson 2 πŸ™‚

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *