Having used both Test::Unit and RSpec, I have to agree with Jim Weirich: the difference between the two is primarily semantics. It seems to me that functionally, they are both equally capable of verifying and specifying code. However, the way in which you write the tests—the semantics—is the primary difference between the two. That being the case, I prefer the semantics of RSpec.
Jim’s post was written back in 2005. Since then, RSpec has developed it’s own Domain Specific Language (DSL) which is really the thing that draws me to it. It feels more natural to develop a test in RSpec than it does in Test::Unit. Here’s a quick example:
Test::Unit
1 2 3 4 5 6 7 8 9 10 11 12 13 | class UserTest < Test::Unit::TestCase def setup @user = User.new end def test_name_setter assert_nil @user.name, "User's name did initialized to something other than nil." @user.name = "Chuck" assert_equal @user.name, "Chuck", "@user did not return 'Chuck' when it was called." end end |
RSpec
1 2 3 4 5 6 7 8 9 10 11 | define "User" do before(:each) do @user = User.new end it "should assign a value to the name when the setter is called and return it when the getter is called" do @user.name.should be_nil @user.name = "Chuck" @user.name.should equal "Chuck" end end |
Here are the things I like about RSpec that I don’t get from Test::Unit.
First, I can read aloud to another developer and he understand exactly what I’m testing. In other words, I don’t have to mentally or verbally interpret my test from code to English. I just type out what it should do and what state it should be in and the RSpec specification takes over from there.
It’s true that you can write a test called “test_that_name_setter_assigns_a_value_to_user” but my eyes and mind more readily interpret spaces. Furthermore, the output from RSpec tells you “User should assign a value to the name when the setter is called and return it when the getter is called.”
Second, I don’t have to specify the message for each assertion. In the Test::Unit example, each assertion was given a message so I would know what the problem was. Generally, I’m more interested in which area of functionality I broke and where I should go to fix it. RSpec tells me which assertion failed and in which area of functionality it failed.
Third, you don’t have to monkey around with Cucumber to make RSpec work. You can use Test::Unit with Cucumber, but it takes a little bit of patchwork.
Overall, for me it just comes down to pretty tests and the natural flow of the RSpec tests. I’m comfortable with Test::Unit’s capabilities, but Ruby has spoiled me into thinking that I need a test framework that’s as natural to me as the Ruby programming language itself.





3 Comments »
David Chelimsky
July 10, 2009
Hey Charles,
Thanks for posting this. I’m glad you like and use RSpec. But Jim’s article, and a lot has changed since then. It’s not just semantics anymore.
Consider pending examples, easily customizable output formatters, nested example groups for improved structure, and component isolation in rspec-rails, etc, etc. These are all things that impact the process of doing TDD much more than the satisfying feeling one gets writing prettier tests. I like that satisfying feeling too, but that’s really only scratching the surface of what RSpec has to offer.
Also – small typo: replace define with describe.
Cheers,
David
Chuck
July 10, 2009
David,
Thanks for the feedback. Is there a good source for picking up on some of those things? Feel free to post some links or email me so that I can do so.
David Chelimsky
July 12, 2009
Here are some links:
http://pragprog.com/titles/achbd/the-rspec-book
http://rspec.info/
http://rspec.rubyforge.org/rspec/1.2.7
http://rspec.rubyforge.org/rspec (for other versions)
http://rspec.rubyforge.org/rspec-rails/1.2.7
http://rspec.rubyforge.org/rspec-rails (for other versions)
http://blog.davidchelimsky.net
Leave a comment