Podcast: Play in new window | Download
There are a lot of tools for testing Rails. Here are links to several of the ones mentioned in this podcast.
You can find my interview with David Heinemeier Hansson here, and my response to his comments on Twitter here.
Finally, here are a few other resources for you to get started with testing Ruby on Rails.
Here’s a transcript of the podcast:
Rails Coach Podcast, Episode 5
Hey, everybody, and welcome back to another Rails Coach podcast. This is Charles Max Wood and this week we’re going to go into testing Rails. You can test Rails in a lot of different ways, and we’re going to talk about some of the libraries that are around for doing that. I’m also going to talk about my approach to it; some of the things that I’m thinking about doing or changing – and I guess we should just dive right in.
First off, I want to point out that there’s been a discussion on Twitter about Test Unit vs. RSpec. Now, if you’re not familiar with Ruby on Rails or who David Heinemeier Hansson is, then I recommend that you go listen to the “Teach Me To Code” podcast. I interviewed David on that podcast and talked a little bit about Ruby on Rails. And that will give you kind of a feel for who he is. He’s the guy that wrote Ruby on Rails and he is the technical partner at 37signals that makes Basecamp and Highrise and a bunch of other products that I used to use. But I don’t anymore. And that’s not the topic for this podcast. Anyway, we’re going to go into some of the things that are available for testing Ruby on Rails. I’m going to go into, first off, the discussion that was had over RSpec and Test Unit. David Heinemeier Hansson, a while back, said that he and 37signals, they used Test Unit, and that Test Unit and Mocha, which is a mocking and stubbing framework were basically all you need for good Ruby on Rails testing. Then he later said that he was a little disappointed by the proliferation of RSpec and Cucumber because he felt like they were a little too complicated and had been cargo-culted upon the Ruby on Rails community. And that started a whole lot of discussion over whether or not RSpec and Cucumber were the right tool. There were people who came out and said, Oh yeah, David’s right. Test Unit all the way. And other people came out and said, Hey wait a minute, RSpec all the way. David, you’re an idiot. And some people had kind of the reaction that I had where we thought about it for a minute and said, I’ve been using Test Unit or RSpec for a while, and I really ought to explore what the differences are and why I might want to use one over the other. I really haven’t had a chance to do that. However, I have used both; I’ve used both on different projects. And so I think it is worth discussing testing tools that are available for Ruby on Rails and what you can do to learn this stuff. So we’ll jump right in here. First off, I use – I’ll let you know – I use RSpec and Cucumber, and I use Factory Girl to generate my objects that I am going to be testing against. And then I use FlexMark for mocking and stubbing. That’s more or less what I use. Now, with Cucumber I use Capybara. And then I’ve recently started using Culerity and Celerity to test my JavaScript. And that has been working, actually, really well.
So, basically I use RSpec to do some of the testing in Cucumber. For example, you can write your assertions or dot-shoulds in Cucumber steps, and if they fail then your Cucumber scenario fails. RSpec I also use for my unit tests. And unit tests are just class-level tests. They usually use some method of mocking or stubbing to isolate your object so that you can test one way or the other, or if you have a dependent object, then you don’t necessarily have to mock that out. It’s a matter of preference as to how deeply and how thoroughly you mock things out. In my case, I really feel like in a lot of cases people mock things out that they really don’t need to. Anyway, I’m not really going to go into that either, other than to say if it’s much simpler just to create a dependent object, do it. If there is a deep algorithm around or something that you haven’t implemented, then you can go ahead and mock or stub an object so that it will behave the way that you need it to in order to test the functionality in your unit test. If it is complicated functionality then you probably should be mocking it, just because if the implementation changes, your test result doesn’t change because the output changed. Because basically, in your unit test, when you are testing something that depends on another object, you should really only be testing its dependency on state or output from the other object. So, anyway, I use RSpec and RSpec gives you kind of a name-spacing feature, where you can do Describe, and then you give it a class name and then a block. And the block is a Do with code in between it and an End. And so then inside there you can do It, and then you give it a string that describes the functionality that you are testing, and another block. And then in that block you can do setup; you can do the actual test. So you get in and you can say, If I set this user’s name to Chuck, then when I retrieve the name from the user, it should be Chuck. And that is kind of a contrived example because in a lot of cases, that’s simple enough to where you would just assume that it is the case and you don’t necessarily need to deeply test it.
But anyway, I also use Cucumber. And Cucumber is kind of the top-down testing. It is built around an approach called BDD, or behavior-driven development. And the idea behind Cucumber is that you can write your specifications in plain English, and then you write steps that parse those – well, you write handlers for the steps that parse the step, and take the information from the step and actually execute it.
So what happens is, you can write something like, given I am logged in, and then what that does is you write a handler that can go and actually goes through the motions of logging you into the website. Then the next step could be “and I am on the home page.” So then it takes you to the home page, slash-home. When I click on Log Out, then it actually triggers a click event on the logout link. Then I should see “You’ve been logged out successfully.” And so then it looks for that content on the page. And it does everything from the top all the way down to the bottom, so you are testing not only your controllers and your views and your models, but you are also testing the interactions between them to make sure that it is displaying the right information. When you are testing things like controllers – when you are unit testing your controllers — in Rails if you use Test Unit then under your test folder you will see Unit, Functional, and Integration. And the Functional tests are your controller tests. You may also see tests for your views and other things. That’s something that they’ve added since I’ve started programming in Rails. I’m not a big fan of testing the views, and I’ll go into why in a minute. But anyway, when you are testing your controllers, then a lot of times what you are going to do is you are going to mock out your models. And then that way they are not dependent on the functionality of the model; they’re just dependent on the values that they are going to get back from the model. And so then what you can do is you can test and make sure that if you get a certain thing back from a method that you wrote on the model, then that gets passed through to the view.
Usually your controllers are pretty slim. Most of your functionality is in your model. So testing the controllers is really, really simple. Testing the views is a little tricky because you really can’t test good layout. There’s not a good way of doing that. So you typically wind up eyeballing it. So testing the view really means making sure that the right data shows up. And in that case, I feel like the integration tests are sufficient. Because then what it does is it makes sure that the data is in the database; it shows up in the view. And that’s exactly what you want. So I never really test the views.
You can also test things like routes and other things. And some of those are worth it; some of them probably aren’t. It really just depends on your understanding of things and your making sure that things work the way that you want them to. Now the testing is really important. I do TDD at the very least, and typically quite a bit of BDD. Which means that I write unit tests before I write model code. And I write Cucumber scenarios before I write the overall feature. And the reason that I do that is so that I understand how the interaction should affect the overall behavior of the application.
And it’s nice because if I really need to, then I can actually send the Cucumber feature over to my client, and they can look at it and say, Yes, this is how I want it to work. Or, No, it’s not. Or, I don’t understand. And then we can kind of work from there.
So it really is quite handy to have. And that’s why I use Cucumber. If I weren’t collaborating with my clients, then I would probably be tempted just to use the integration portion of the testing frameworks, either in RSpec or Test Unit. And simply use the Capybara library and test things directly, rather than writing out the English steps, because I find those a little bit tedious as a programmer. But I find that they are useful if I am collaborating with somebody that is not a programmer.
Anyway, those are some general thoughts on testing Ruby on Rails. You can go and find – I’ll put up some links to some resources on Cucumber and RSpec and Test Unit and learning how to use some of these things. And hopefully this helps you get started testing your Ruby on Rails application. You’ll find that as you get into the Rails community that this is a big deal. So, as you continue on your journey of learning Ruby on Rails, you’ll start to pick up – Oh, this is important, testing is important. And you’ll start to see why people do the testing and what they gain out of it.
Real quickly, I feel like I gain a couple of things from testing, especially TDD. One is that I feel like I understand a problem before I approach it, which really helps me write the code better. The other thing is, I know immediately if somebody else has changed something that breaks the expected functionality, because I’ve put these expectations on the code. So if somebody else is coding in the same code base and they break something, when I run the tests then I’ll get notified. And if I am running continuous integration, then that’s something that really works in my favor as far as letting me know immediately, when I checked in, that something broke. And letting them know too. Really, it’s just a good exercise in thinking about these things and writing great code. So that’s what I like about the approach.
Now, if you want to get a hold of me, you can get a hold of me at chuck@teachmetocode.com
If you want some coaching or you want to learn Ruby on Rails, then you can call me at that number or email me. You can call me at 801- 367-6164. That’s my cell, so you can get me just about anytime and I’ll pick up. I’ll be happy to walk you through whatever you are working on and help you get going.
If you have a Ruby or Rails or Sinatra or some application that you want me to build for you, I do that too. You can reach me in those same ways. I’m also working on posting the videos to these. And I just got some new software that does – what is it? – It’s transcription. So I got some software that should help me transcribe these episodes so that you can benefit from them in text as well as in audio. And I’m posting videos. It’s just kind of a talking head right now. On YouTube. So you can go on YouTube and see me talking to you, if you would prefer.
Those are great ways to do it. The show notes are at RailsCoach.com. Thank you for listening.
Finally, here’s the video version:


I got those fixed. Sorry about that.
- spam
- offensive
- disagree
- off topic
Like