I don't use RSpec a lot any more these days. I much prefer Shoulda, heck I even started using Rails integration tests again (using Shoulda of course), because sometimes the additional abstraction of Cucumber is just too much. Any way, there's some things I liked about RSpec, and they were not related to the features of the testing DSL itself, but more to the tool RSpec. It has a neat formatter that'll output the ten slowest-running tests. I also found the colored list of full test names to be very helpful.

So I scratched my itch last weekend and brought that goodness to Shoulda. Our test suite is starting to get a bit slow, and it already served us well to find the slowest one. I like the approach of rinse and repeat to squeeze some valueable dozens of seconds out of a test suite with that technique.

So without further ado, I give you shoulda-addons, my little patch set to bring both test profiling and a colored list of full test names to you Shoulda test suite. I'm sure it'd work with normal Test::Unit or MiniTest without much effort, but for now it's made for Shoulda, and it looks like this:

Screen shot 2009-10-19 at 22.11.07

While adding in the profiling was pretty straight forward, getting the colored output was pretty messy, and I'm not proud of it, especially considering that Test::Unit and MiniTest go different routes of outputting the little dots F's and E's.

The package is up on GitHub, can be installed from Gemcutter via gem install shoulda-addons, and should work with Ruby 1.8 and 1.9. I also tested it with Mocha included, so let me know if something doesn't work for you.

This is the bundle that'll make TextMate almost as good as warm apple pie. RubyAMP comes along with a few additions to Ruby coding in TextMate, but boy do they rock.

Some of its features:

  • Grep for Method
  • Grep for Class/Module, both method and class/module grep use the word under the cursor
  • A much faster (compared to "Find in Project") "Grep in Project"
  • Code completion with data from all open files
  • An intelligent "Go to file" which will try to find something matching the word under the cursor
  • Run RSpec in the debugger

Here's code completion in action:

Picture 2

On the website you'll find a video showing most of the features. Pretty neato. Ruby and Rails development on the Mac just got even sweeter.

Via Samurai Coder.

Mocking is a great part of RSpec, and from the documentation it looks insanely easy. What had me frustrated on a current project is the fact that the mocks and stubs wouldn't always do what I'd expect them to do. No errors when methods weren't invoked, and, the worst part, mocks wouldn't be cleaned up between examples which resulted in rather weird errors. They only occurred when run as a whole with rake spec but not when I ran the specs through TextMate.

I was going insane, because noone on the mailing list seemed to have any problems, same for friends working with RSpec. Then I had another look at the RSpec configuration.

Turns out, the reason for all of this is that Mocha was used for mocking. Switching the configuration back to use RSpec's internal mocking implementation, everything worked like a charme from then on.

So what you want to have in your SpecHelper isn't this:

Spec::Runner.configure do |config|
  config.mock_with :mocha

but rather

Spec::Runner.configure do |config|
  config.mock_with :rspec

or no mention at all of mock_with which will result in the default implementation being used which is, you guessed it, RSpec's own.

When using CruiseControl.rb for continuous integration, and RSpec for testing, the defaults of CruiseControl.rb don't play that nice with RSpec. However, that can be remedied pretty simply.

By default CruiseControl.rb runs its own set of Rake task, which invoke a couple of Rails' tasks, including db:test:purge, db:migrate and test. You do want the first ones, but you'd rather have CruiseControl.rb run your specs instead of your the (most likely non-existing) Test::Unit tests.

Before running its default tasks it checks whether you have a specific task configured in your project settings, and if you have a task called cruise in your project's Rakefiles. You can use both, but I just declared a task cruise in the Rakefile, and I was good to go.

That task can to pretty much the same as the original CruiseControl.rb implementation, and even be shorter since it can be tailored for your project, but invokes spec instead of test. One caveat is to set the correct environment before running db:migrate. I split out a tiny prepare task which does just that, and can do a couple of other things, if necessary, like copying a testing version of your database.yml.

desc "Task to do some preparations for CruiseControl"
task :prepare do
  RAILS_ENV = 'test'

desc "Task for CruiseControl.rb"
task :cruise => [:prepare, "db:migrate", "spec"] do

Simple like that. The task spec will automatically invoke db:test:purge, so you don't need that.

I recently started picking up RSpec for a current project. Not too far along the way I found myself wanting to test a SOAP web service written with Active Web Service with it.

Given that these map to controllers it's pretty easy to do that. You can basically use the same things that you can use in Rails' function tests. All you need to do is include the correct helper that defines the methods, in your specification.

require 'action_web_service/test_invoke'

And that's it. From then on you can test your web services like controllers, given that you have an Service::SearchApi that uses the Service::SearchController, you can just do this:

describe Service::SearchController do
  it "should find users with a valid input" do
    users = invoke :find_users, "quentin"
    users.should have(2).items
    users.first.should be_instance_of(User)

There. It's that easy.

Tags: rspec, testing

The RSpec and Behaviour-Driven Development edition: * Behaviour-Driven Development. An excellent introduction to RSpec and BDD by Bruce Tate.

Tags: links, rails, rspec, ruby