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.
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:
source 'https://rubygems.org'
gem 'rspec'
Let's start writing our first test in 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:
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.
It's time to write our first test:
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:
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.
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.
To install RSpec:
$ gem install rspec
To add to Gemfile
:
gem 'rspec'
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