It’s hard to believe that, for all of Smalltalk’s elegance, it isn’t more widely accepted. I just read the SUnit chapter in Squeak By Example. The SUnit TestCase class has a resumable assert method (TestCase#assert:description:resumable:). The use case for this is testing objects in a collection. Here’s a code example:
(1 to: 30) do: [ :each | self assert: each even description: each printString, ' is odd' resumable: true]
This code produces a test failure and outputs each object in the collection that fails the test (every odd number, in this example).
I decided that I wanted something like that in Ruby. Well, I want it in Java too, but coding in Java’s no fun
I was thinking of something like this:
1.upto 30 do | each | assert_and_resume each % 2 == 0, "#{each} is odd" end
After poking through the TestCase source, I decided the easiest approach would be to write a custom assert, wrapping the assert_block method. I just needed to be able to catch the failed assertion and report the failure without stopping the test method.
So I wrangled a little code and came up with a solution that works like this:
1.upto 30 do | each | assert_and_resume( "#{ each } is odd" ) { each % 2 == 0 } end
Pretty close to what I was thinking.
And here’s the implementation:
module Test module Unit # Resumable assertions are in a different module then the other # assertions because they have a dependency on # TestCase#add_failure. The standard assertions can be included # anywhere, so including Resumable assertions in the Assertions # module might break existing code. module ResumableAssertions require 'test/unit/assertions' def assert_and_resume( description, &block ) begin assert_block description, &block rescue AssertionFailedError => e add_failure e.message, e.backtrace end end end # Now we hook our assertion up to the test case. I could have just # re-opened TestCase, but I wanted to keep the Assertion logic # separate from the TestCase logic, as was the original author's # design. require 'test/unit/testcase' TestCase.send( :include, ResumableAssertions ) end end
Not much to it. The only other change that I might like to make is to modify the output so that it’s clear that one method failed many times. On a lark, I ran this through ci_reporter and then used Antwrap to generate a junit report. Here’s an snapshot of what that report looks like:





Recent Comments