Now that testing is a normal part of my daily workflow, I think it’s a great time to go over some of the testing tools that I use here at thoughtbot.
Shoulda
Typing too much makes testing no fun at all. I’m actually coming from the RSpec world, and thankfully it was pretty easy to switch over to Shoulda from it. Here’s what I like best about it:
context
andsetup
blocks makes testing ridiculously simple and DRY.before_should
: Basically, you can set up expectations with your favorite mocking framework in these blocks, which run before thesetup
block in the givencontext
.- Macros that just save tons of time. Simple ones like
should_redirect_to
are actions that need to be tested all the time, and luckily there’s a whole suite of them for both ActiveRecord and ActionController. - Custom macros that can be easily dropped in to test the same actions in
multiple places. I do miss RSpec’s
it_should_behave_like
though, but this works decently.
Mocha
The concept of mocking and stubbing in general is somewhat new to me, and it’s definitely been difficult to learn how to use effectively. It’s starting to become natural though, and I don’t mind the speedup that testing in isolation gives. The majority of our projects use Mocha, which does the job just fine. I’ve also been looking into RR, which has a much cleaner syntax and some additional features, but usually my daily mocking is done with Mocha. The most important thing for me to remember is to avoid situations where test pass but the code is broken due to excessive stubbing of behavior. The sweet spot with this is to use integration testing to cover all the bases.
factory_bot
If you’ve ever dealt with the frustration that is Rails fixtures, then you know
the breath of relief that
factories can give your
tests. Being able to generate new models with a simple Factory(:post)
call
makes testing ridiculously easy. Some of the latest features I’ve been using is
the :parent
option on Factory.define
, which allows you inherit attributes
from another factory. Clearance has a great example of
this
in how it creates a Factory(:email_confirmed_user)
that descends from
Factory(:user)
.
Cucumber
I’ve learned about user stories in classes, but being able to write them in plain English and run them with Ruby has totally blown me away. Outside-in development is a great way to approach features that need to be built and tested from the ground up. Ben Mabey’s presentation at MountainWest RubyConf has a great example of how this development method works if you haven’t tried it out yet. The best part I find is that it can be read by clients or developers coming into the project, and it can be used outside of the Rails environment as well. Take some time and look into Cucumber if you haven’t already, and start at their fantastic site.
FakeWeb
Mocking out external HTTP calls is difficult. If you’re working with any sort of API from another site and you want to ensure that your code is actually submitting to it, relying on FakeWeb is a good choice. The syntax and setup is really simple, and it will usually look something like this:
require 'fake_web'
FakeWeb.allow_net_connect = false
FakeWeb.register_uri(:post, "http://somesite.com",
:string => 'response body')
This little snippet will cause FakeWeb to throw errors if any other HTTP calls are made outside of the ones registered. The final line will tell the library to return the given string when that URL is hit from the application with a POST request. Like most projects in the Ruby world, it just works.
Testing in your shell
Being a convert to vim from
TextMate, running
tests usually isn’t as simple as doing Cmd+R. Luckily there’s two tools that
help out with this. One is autotest,
which I’ll run if the test suite for the app I’m working with doesn’t take too
long. What I love best is that it fires off the test immediately after a :w
in
vim, so I don’t have to do any sort of context switching to run the test. It can
get annoying though, and modifying your ~/.autotest
to not run the entire
suite after fixing a failed test helps cut that
down. Another helpful thing that some of the thoughtbotters use is a zsh script
that adds autocompletion for running unit and
functional tests. Basically just type tu
or tf
, and tab away.
If you know of other testing tools that we should be looking into, speak up in the comments!