Today I’m releasing test/spec 0.3, a library to do BDD with Test::Unit.
(See below for changes in version 0.3.)
What is test/spec?
test/spec layers an RSpec-inspired interface on top of Test::Unit, so you can mix TDD and BDD (Behavior-Driven Development).
test/spec is a clean-room implementation that maps most kinds of Test::Unit assertions to a ‘should’-like syntax.
Consider this Test::Unit test case:
class TestFoo < Test::Unit::TestCase def test_should_bar assert_equal 5, 2 + 3 end end
In test/spec, it looks like this:
require 'test/spec' context "Foo" do specify "should bar" do (2 + 3).should.equal 5 end end
test/spec has no dependencies outside Ruby 1.8.
Mixing test/spec and test/unit
test/spec and Test::Unit contexts/test cases can be intermixed freely, run in the same test and live in the same files. You can just add them to your Rake::TestTask, too. test/spec allows you to leverage your full existing Test::Unit infrastructure.
test/spec does not change Test::Unit with the exception of monkey-patching Test::Unit::TestSuite to order the test cases before running them. (This should not do any harm, but if you know a way around it, please tell me.)
These assertions are not included in Test::Unit, but have been added to test/spec for convenience:
a.should.be operator(where operator is
should.output, to check what is printed
With more complex assertions, it may be helpful to provide a message
to show if the assertion has failed. This can be done with the
RUBY_VERSION.should.messaging("Ruby too old.").be > "1.8.4" (1 + 1).should.blaming("weird math").not.equal 11
Custom shoulds (“Matchers”)
To capture recurring patterns in parts of your specifications, you can define custom “shoulds” (RSpec calls them “matchers”) in your contexts, or include modules of them:
context "Numbers" class EqualString < Test::Spec::CustomShould def matches?(other) object == other.to_s end end def equal_string(str) EqualString.new(str) end specify "should have to_s" 42.should equal_string("42") end end
Alternatively, your implementation can define
CustomShould#assumptions, where you can use test/spec assertions
instead of Boolean predicates:
class EqualString < Test::Spec::CustomShould def assumptions(other) object.should.equal other.to_s end end
CustomShould by default takes one argument, which is placed in
self.object for your convenience.
CustomShould#failure_message to provide a better error
SpecDox and RDox
test/spec adds two additional test runners to Test::Unit, based on the console runner but with a different output format.
SpecDox, run with
like RSpec’s output:
spec.output - works for print - works for puts - works with readline
RDox, run with
-rr) can be
included for RDoc documentation:
== spec.output * works for print * works for puts * works with readline
SpecDox and RDox work for Test::Unit too:
$ ruby -r test/spec test/testunit/test_testresult.rb -rs Test::Unit::TC_TestResult - fault notification - passed? - result changed notification Finished in 0.106647 seconds. 3 specifications (30 requirements), 0 failures
Akin to the usual Test::Unit practice, tests quickly can be disabled
xspecify. test/spec will count the
disabled tests when you run it with SpecDox or RDox.
Since version 0.2, test/spec features a standalone test runner called specrb. specrb is like an extended version of testrb, Test::Unit’s test runner, but has additional options. It can be used for plain Test::Unit suites, too.
$ specrb -a -s -n should.output should.output - works for print - works for puts - works with readline Finished in 0.162571 seconds. 3 specifications (6 requirements), 0 failures
specrb --help for the usage.
Changes in version 0.3
should.be_nilhave been deprecated. Use the dot-variants of them. These assertions will be removed in 1.0.
specrb -anow includes
-Ilibby default for easier out-of-the-box testing.
- Added custom shoulds.
- Added messaging/blaming.
- Added disabling of specifications.
- Small bug fixes.
- Gem available.
Installing with RubyGems
Since version 0.3, a Gem of test/spec is available. You can install with:
gem install test-spec
(It may take some time for the index to be updated and the mirrors propagated.) I also provide a local mirror of the gems (and development snapshots) at my site:
gem install test-spec --source http://chneukirchen.org/releases/gems
Version 1.0 (February 2006): first stable release.
Please mail bugs, suggestions and patches to firstname.lastname@example.org.
Darcs repository (“darcs send” is welcome for patches):
- Eero Saynatkari for writing should.output.
- Jean-Michel Garnier for packaging the first gem.
- Mikko Lehtonen, Jan Wikholm, Matt Mower and Michael Fellinger for testing the gem.
- Thomas Fuchs for script.aculo.us BDD testing which convinced me.
- Dave Astels for BDD.
- The RSpec team for API inspiration.
- Nathaniel Talbott for Test::Unit.
Copyright (C) 2006, 2007 Christian Neukirchen
test/spec is licensed under the same terms as Ruby itself.
Where can I get it?
You can download test/spec 0.3 at:
Alternatively, you can checkout from the development repository with:
darcs get http://chneukirchen.org/repos/testspec
(Patches using “darcs send” are most welcome.)
Happy hacking and have a nice day,
ea043ab5837994179d4659aa1e2fcc88 test-spec-0.3.0.tar.gz d0e1c45c2e814cc26a7967232ca99f6c test-spec-0.3.0.gem
NP: The Rolling Stones—Gimmie Shelter