There are a lot of tools for testing Rails. Here are links to several of the ones mentioned in this podcast.
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.
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 firstname.lastname@example.org
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: