Lesson Weekend

Let’s practice using TDD with Ruby. We’ll create a program that returns a string of words in title case and use a tool called RSpec for our testing.

Project Setup


Install RSpec by running $ gem install rspec from your terminal. Note that you can be located anywhere in your computer when you run the gem install [package-name] command, since gem knows to install the package to a directory within your original Ruby installation folder. To find the exact install location, type in gem env in your terminal, and then look for the output called GEM PATHS. While you probably won't need that information, it can be helpful to understand how all of our tools work together.

RSpec has some nice color formatting that makes its results easier to read. To add this formatting, create a file called .rspec in your home directory, type --color in it, and save it.

Next, let's create our project directory and call it title_case. In our root directory, we'll add two more folders: lib and spec. Add a file called title_case.rb in lib and a file called title_case_spec.rb in spec. Note that we use underscores and all lower case letters for Ruby file and directory names.

Next add a Gemfile file in the root directory with the following contents:

Gemfile
source 'https://rubygems.org'

gem 'rspec'

Let's start writing our first test in title_case_spec.rb:

title_case_spec.rb
require('rspec')
require('title_case')

describe('#title_case') do
  # eventually put specs here
end

The require method runs all the code from a gem or another file. Ruby has a list of folders it checks when you run a command and lib is in the load path, so it's not necessary to put the relative path of title_case.rb.

describe is an RSpec method and 'title_case' is its argument. The argument can be anything we want, but it's convention to use the name of the class we're working on, followed by a hash, followed by the name of the method. In this case, we aren't adding the method to a class so we'll just use a hash followed by the name of the method.

All of our specs will go inside this do...end block.

Let's add some code to title_case.rb as well:

title_case.rb
def title_case(sentence)
  # eventually put code here
end

We now have our folders, files, a #title_case method, and the beginning of a spec file.

Next, run $ rspec in the root directory of your project. This will run all of the specs in the spec folder. It should say No examples found. along with 0 examples, 0 failures in green.

Writing Our First Test


It's time to write our first test:

title_case_spec.rb
describe('#title_case') do
  it("capitalizes the first letter of a word") do
    expect(title_case("beowulf")).to(eq("Beowulf"))
  end
end

The syntax of RSpec is very similar to English. If you read the spec aloud, it would say "describe #title_case: it capitalizes the first letter of a word." We can put any description between it and do. We should strive to be both concise and descriptive.

expect is an RSpec method that takes the argument title_case("beowulf"). to and eq are also methods provided by RSpec. In plain English, this test is expecting the result of calling method title_case("beowulf") to equal "Beowulf".

Let's run $ rspec again. We now have a failing test:

Failures:

  1) #title_case capitalizes the first letter of a word
     Failure/Error: expect(title_case("beowulf")).to(eq("Beowulf"))

       expected: "Beowulf"
            got: nil

       (compared using ==)
     # ./spec/title_case_spec.rb:6:in `block (2 levels) in <top (required)>'

Finished in 0.07202 seconds (files took 0.51045 seconds to load)
1 example, 1 failure

That's the error we want: we haven't put any code in our method yet. Let's make this test pass:

title_case.rb
def title_case(sentence)
  sentence.capitalize!
end

We use the String#capitalize!() method to capitalize the first letter of the string.

If you run $ rspec again, you'll see that the test passes.

$ rspec
.

Finished in 0.02198 seconds (files took 0.53477 seconds to load)
1 example, 0 failures

Anytime we get a passing test, we should commit our code.

Writing a Second Test


Let's go through one more TDD cycle together. First, the test:

describe('#title_case') do
  ...

  it("capitalizes the first letter of all words in a multiple word title") do
    expect(title_case("the color purple")).to(eq("The Color Purple"))
  end
end

After running $ rspec, we get the failure: expected: "The Color Purple", got: “the color purple. Now, let's make it pass:

def title_case(sentence)
  split_sentence = sentence.split
  split_sentence.each do |word|
    word.capitalize!()
  end
  split_sentence.join(" ")
end

Now our test is passing again, and it's time to commit our code.

And with that, we've covered the basics of using RSpec. In the next lesson, we'll work through one more example of TDD and the Red-Green-Refactor workflow with RSpec.

Adding RSpec


To install RSpec:

$ gem install rspec

To add to Gemfile:

gem 'rspec'

Sample Test


require 'rspec'
require 'name_of_class_file'

describe('#method_name') do
  it("does something") do
    expect(method_name()).to(eq("some result"))
  end
end

Lesson 2 of 4
Last updated August 7, 2022