How you should be doing testing in Rails and how to get started

Here I show you a good way to do testing in Rails (especially if you are a beginner tester) plus instructions on getting started.

Why test?

Testing is a good practice. You should be doing it. It will make you a better programmer and save you a great deal of headache as your web app grows up. It is especially important when working alongside other programmers. Testing is not perfect though so don't try to be perfect. Just get started, and you will improve as time goes on.

How should I be testing?

You should be:

Ignore all the other test strategies and tools out there - especially Cucumber (cuke makes me want to puke). It's awkward and arguably a significant waste of time. But it's even more a waste of time to test your controllers, helpers, and views separately. Don't.

Let's get started.

rspec

Installation

That's it, you can now run 'rake spec' in your terminal, and it will run through all your specs (which are currently at zero count).

Model testing

Setup

Before we get to the rspec testing we need to delete the test/* folder that rails creates by default. (We are using rspec, not test/unit, so we won't need the test/* folders. All our tests will live under spec/*.)

Next let's create the models folder and the person_spec.rb model spec.

Writing the model test

Open up person_spec.rb in textmate or your text editor of choice and let's write our first spec.

Run 'rake spec' in terminal, and you should get back the response of "1 example, 0 failures". Congratulations. :)

Time for some test driven development. We have decided that every person should have a first_name and last_name. (No use in having a person without one). Let's write two specs to test for this. They should both fail.

Run 'rake spec', and you should receive the response back '3 examples, 2 failures'. Open up the person.rb model and add the validates_presence_of.

Run 'rake spec' again, and you should receive the response back '3 examples, 0 failures'. Nice work, you just did test driven development.

Next let's refactor things slightly using our spec_helper.rb to store some reusable code. This is optional and isn't so useful with such a small suite of tests, but once your test count climbs to 50 or more it is really nice to have a setup similar to the following. It basically uses helper methods inside of spec_helper.rb (which is being required with the line 'require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')').

person_spec.rb

spec_helper.rb

Good work. You've written a few model tests to test your person.rb model pretty well. Let's move on to integration testing.

Integration testing

Before I demonstrate integration testing, let me say that many programmers test their views, helpers, and controllers separately. This is not smart and if you are doing that you should stop. Take Merb's testing approach as an example. Merb's testing framework encourages the developer to test the final http response rather than worry about testing your views, controllers, and helpers separately. Afterall, these three items are working together to create the final http response. It makes a lot of sense and saves a lot of time. (Yehuda Katz can tell you more about this in his video on merb testing).

Rails doesn't have Merb's fancy response testing, but it does have integration testing using the powerful webrat. (Cucumber uses Webrat - which is about the only thing I like about cucumber.)

Setup

Add config.gem 'webrat' to your config/environments/test.rb file

Open up spec_helper.rb and add the webrat configure block.

Create the spec/integration folder and file

Write the integration test

Now you are ready to write your first integration test using webrat. We are going to test some basics from the people scaffold we created. Edit spec/integration/people_spec.rb, make it look like the following, and run 'rake spec' again. You should receive the response back '5 examples, 0 failures'.

What is going on here?

The majority of the above code is your standard rspec (before(:each) blocks, describe blocks, it "should do something" blocks, etc). The webrat methods we are using are 'visit' and 'response'.

visit simulates an actual user visiting your website. You don't see it happen, but webrat is actually (sort of) visiting the site just like a normal user would in their browser. To visit other pages just do visit '/your/path'.

After the visit command is employed, webrat returns a response from the webpage. This is essentially the http response a visitor's browser would receive. Here we are checking the response.status to verify it returned a 200 OK. To inspect the available response options use 'puts response.inspect'.

Now let's test that the response contains certain text. You can use webrat's have_selector or have_xpath methods to determine this. In fact, most of the time with webrat those are the methods you will be using in conjunction with visit and response. Let's check that the people/new page contains the correct form fields.

Depending on how you built your scaffold all these tests will pass or you might get 2 failures back. I got two failures. Let's fix those two errors by adding the appropriate form fields to our views/people/new.html.erb file. It should look something like the following.

Great work. You've already created 8 specs to test your application. Now just repeat the process while consulting the rspec docs andthe webrat docs, and before you know it you will find testing a joy and a valuable addition to your programming knowledge. Good luck, and you should follow me on twitter here if you have questions.

Also, the example app I built along with this tutorial is here on github.