Testing With RSpec
Meet Mikey:

When we last saw Mikey he was trying his hand at VIM. You can read more about VIM and Mikey’s past adventures here.
It’s now the dog days of summer and Mikey just received word from his parents that the information regarding his class schedule for next school year has arrived in the mail. Mikey reads the letter and learns that his homeroom teacher will be Mr. Jentzen in room 211, along with 22 other students. Mikey calls his friend Tommy to ask which teacher he has and learns that Tommy will be across the hall with Ms. Wroble in room 212. This makes Mikey nervous. He just moved to a new town and hasn’t really had a chance to make any friends. Mikey was hoping he would be in the same classroom as Tommy, who could help him with meeting all the cool kids. How can Mikey ever expect to get to know everyone in his class all on his own?
We already know that Mikey is quite the programmer, and that he will jump at any opportunity which allows him to write code. As he ponders how he is going to prepare for the upcoming school year, he realizes he can write a simple program to aid him in getting up to speed on everyone in his class. He reads the list of his classmates to Tommy, who gives Mikey information about each of the students. Tommy also offers to send Mikey information regarding the students in Ms. Wroble’s class in order to familiarize Mikey with the other students in their grade.
As Mikey sits down to begin his project he reminds himself that there is a lot riding on the outcome of this project. He wants to make sure that his classmates don’t think he is a dweeb, and if does a poor job preparing he risks making a bad first impression. Mikey decides to write some RSpec tests before he even begins coding the project in order to help focus his efforts and keep him on track.
What is RSpec, and Why Bother Testing?
RSpec is a unit test framework for Ruby. It is used as a Behavior driven development tool, meaning that it is used to test what the application does, as opposed to testing how the application does it.
There are several benefits to writing tests for your application. The most obvious reason is that it helps to ensure your application is functioning properly. Apps are generally designed with the intention that they will consistently act in a certain manner, and by comparing our expectations for the application to the results it gives to us, we are able to verify whether or not it is working. It also provides the programmer, as well as anyone else who may be reviewing the code, with a sense of clarity in regards to what the program is trying to accomplish. Taking the time to clearly define what the app is trying to do pays dividends in the long run. It aids whoever is writing the code to not only stay on track, but to also prevent them from investing time into implementing unnecessary features and functionality, among other things.
The Test Suite Environment
Mikey is ready to begin. He opens his terminal and makes a new directory for his project. Within the root directory of the project, he creates a folder for all of the tests, called spec:
mkdir specWithin the spec folder, Mikey is going to create a file that will store the tests for his program. Mikey goes on ahead and creates the file:
touch student_spec.rbAs long as Mikey is in the root of this directory, each time Mikey enters “rspec” into his terminal, the app is going to look for a folder called ‘spec’ and run each of the tests included within. In this instance Mikey is testing his student.rb file, which contains all the logic for how he will be keeping tabs on his new classmates.
Getting Acquainted With RSpec Syntax
Mikey writes a basic method in order to test that RSpec is up and running. Within the student.rb file he defines the #return_name method, which will simply take a name and return it.
def return_name(name)
name
endWithin the spec file, Mikey includes the test for his #return_name method:
describe "initial test" do
context "when testing the RSpec environment" do
describe "#return_name" do
it "should return the name passed to it as an argument" do
expect(return_name("Mikey")).to eq("Mikey")
end
end
end
endLet’s briefly review the syntax.
Describing ‘describe’
If you can’t describe what you are doing as a process, you don’t know what you’re doing. — W. Edwards Deming
As we mentioned earlier, the sole function of testing is not to ensure that an application is behaving properly. Tests are also used to help us understand what it is actually doing. The describe keyword helps us to conceptualize what is actually being tested. describe can be passed either a string or a class name and requires that you pass a block argument, which generally includes a number of individual tests.
In the example above, Mikey first uses describe to indicate that we will be testing the initial test. He then uses it again to clarify which method is being tested.
It’s All About Context
context is very similar to describe in that it can take a string or a class name as an argument. It also uses a block. The purpose of using context over describe is that context encapsulates tests of a certain type. For example, if I were implementing tests for a class I defined, I may use the context keyword to distinguish instance methods from class methods.
In the example above, we see that Mikey used the context keyword to let us know the test is intended to confirm that the RSpec environment is properly set up.
It Does What It’s Told
The expect keyword defines an expectation, which is what we use in order to determine whether our app is running as intended. Each expect keyword is generally followed by the to keyword (or in some instances, not_to). The value of whatever is contained within our expect invocation is compared to our expectation. If the results are the same the tests will pass, otherwise they will fail.
A quick glance back at the example shows that Mikey expected the return value of #return_name(“Mikey”) to equal “Mikey”.
Testing Our Tests
Now that Mikey knows his environment is properly set up, it’s time to get to writing some tests. But first, Mikey needs to add some sample data to the spec file. These variables will be similar to the data that Mikey has on his classmates, and he will use these variables throughout the test suite as they accurately represent the type of information his app will be handling. Be sure to take note of the before(:all) hook. This block will run one time before any of the tests are run, enabling us to use the variables for our tests.
Let’s look at Mikey’s fake student information:
before(:all) do
@tommy = Student.new({
name: "Tommy",
true_pal: true,
clique: "cool kids",
teacher: "Wroble",
homeroom: 212,
intelligence: 7
}) @danny = Student.new({
name: "Danny",
true_pal: false,
clique: "smart kids",
teacher: "Jentzen",
homeroom: 211,
intelligence: 10
})
end
Now Mikey has a list of students to test his methods on.
As for the tests, Mikey knows that for each student, he is going to want to know their name, whether or not they are a friend of his, which clique they belong to, their homeroom teacher, their homeroom number and their intelligence. Let’s take a look at the test Mikey wrote for his Student’s class #initialize method.

As we can see, Mikey has made the expected behavior of his initialize method very clear. He even ensures that the information being passed to the method are of the correct class type. Since he has used writing the test as an opportunity to figure out exactly how the method should work, he is able to define the method with relative ease.
After defining the Student #initialize method Mikey runs RSpec and watches the tests pass. Now, Mikey wants to see what will happen if he passes in an improperly formatted student into the test:
before(:all) do
@dummy = Student.new({
“Name: = dumb”,
true_pal: “true”,
clique: "cool kids",
teacher: "Wroble",
homeroom: two-twelve,
intelligence: 7
})
endMikey runs RSpec and watches the tests fail.
Mikey continues to write tests for each of the methods his application is going to implement before moving on to define them. Since his tests check to ensure the app is behaving the way it is intended, Mikey can proceed with learning all there is to know about his classmates in confidence. Go Mikey!
Additional Material
Here is a link to the Github repository that this blog post used as a model. Feel free to reference and/or clone it if you are seeking additional information on how to implement tests of your own:
