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
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
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.
[poll id="3"]