I use xUnit.net in the .NET world, which was created and is maintained by my friend Brad and my skip-level boss Jim. There is one thing from xUnit.net that I was really missing when using Test::Unit: Record.Exception. Here is a C# example of how Record.Exception can be used:
using System; using System.Collections.Generic; using Xunit; namespace ColorCode.Compilation { public class LanguageRule_Facts { public class Constructor_Facts { [Fact] public void It_will_throw_when_the_regex_is_null() { DictionaryThe important thing about Record.Exception is that it allows you to stay true to the 3A pattern (arrange, act, assert), even though you are dealing with an exception. This is pretty important to me. So I threw together a quick and dirty Ruby method to do the same thing:captures = new Dictionary { { 0, "fnord" } }; Exception ex = Record.Exception(() => new LanguageRule(null, captures)); Assert.IsType (ex); Assert.Equal("regex", ((ArgumentNullException)ex).ParamName); } } } }
def record_exception begin yield if block_given? return nil rescue Exception => ex return ex end endYes, it's ridiculously simple. But now I can do this:
require "test/unit" require "assert" require "client" class ClientTests < Test::Unit::TestCase def test_init_will_throw_when_io_is_nil ex = record_exception do client = Client.new(nil, Object.new) end assert_not_nil(ex) assert_equal(ex.to_s, "io must not be nil.") end endThis solves the second-most severe pain point I had with Ruby TDD. There are many more yet, and they'll likely be the subject of future 'blog posts.
http://twitter.com/anglicangeek