This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: Some nice new features of Test::Unit 2.0.1
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
Kouhei Sutou has released Test::Unit 2.0.1 which as added a few new nice features. A couple of these were ones that I requested, some were borrowed from Mathieu Martin, and others were ideas taken from the Shoulda library.
Lets start with the simple but useful features for testing error conditions. These two features were inspired by Mathieu Martin. In his blog entry that I linked to above, Mathieu complained that it was annoying that assert_raise mandated an argument. So, as of Test::Unit 2.0.1, the assert_raise method now defaults to Exception if no argument is specified.
assert_raise{ 0/0 }
This is handy when you have some method that you know should raise an error, but you either don't know or don't care in advance what particular error it raises, so long as it raises some error.
If you want to be more specific than Exception when testing for errors without having to resort to a list of specific exception classes you can now use the assert_raise_kind_of method. I've found this particularly useful for cross-platform testing, where different platforms raise different flavors of SystemCallError. For example:
Another complaint brought up by Mathieu was that there was assertion to test for a particular error message. Since I've had this particular need myself from time to time I suggested it to Kouhei and he also agreed that it was a good idea. The result is that Test::Unit 2.0.1 now has the assert_raise_message assertion. Here's a quick example:
assert_raise_message("divided by 0"){ 0/0 }
He's also added a few other assertions, such as assert_compare, assert_const_defined, assert_not_const_defined, and assert_fail_assertion, which is a strange sort of meta-assertion that doesn't strike me as particularly useful but there you go. On top of that there are a few other features you should check out, such as the ability to control certain aspects of Test::Unit's behavior with a YAML config file.
While I was at the Great Lakes Ruby Bash, Jim Weirich mentioned the idea of context blocks from the Should library. Here's an example:
class UserTest < Test::Unit::TestCase
context "A User instance" do
setup do
@user = User.find(:first)
end
should "return its full name"
assert_equal 'John Doe', @user.full_name
end
end
end
In short, it lets you create multiple context-specific setup methods within a particular test case. This is handy when you have certain setup requirements that are only really useful, necessary or wanted for a subset of the test case as a whole. I thought this was a nice idea, submitted it to Kouhei, and he implemented it. The syntax isn't quite as pretty as Shoulda, but it's not bad and you get similar if not identical semantics:
class UserTest < Test::Unit::TestCase
def setup
@user = "me"
end
def test_full_name
assert_equal("me", @user)
end
class ProfileTest < UserTest
setup
def setup_profile
@user += ": profile"
end
def test_has_profile
assert_match(/: profile/, @user)
end
end
end
On a somewhat related note, I've decided that the assert_const_defined isn't particularly useful in practice because of MRI's dubious behavior for const_defined?, which is really more like const_defined_in?. Meaning, for example, that it will fail for subclasses or classes that mixin a particular constant.
In practice that means that I'll stick with assert_not_nil for testing constants because of cases like this:
The second assertion fails because FNM_NOESCAPE is not actually defined specifically in the File class. It's not in IO, either. In fact, I'm not sure where the heck it's defined. I'd have to dig through the C source. But, instead, I just won't use it.
Anyway, there you go. Hope you find the new features useful.