[ANN] test/spec 0.3, a BDD interface for Test::Unit

Hello,

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 does not include a mocking/stubbing-framework; use whichever
you like to---FlexMock and Mocha have been tested.

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.)

== Wrapped assertions

assert_equal: should.equal, should ==
assert_not_equal: should.not.equal, should.not ==
assert_same: should.be
assert_not_same: should.not.be
assert_nil: should.be.nil
assert_not_nil: should.not.be.nil

assert_in_delta: should.be.close
assert_match: should.match, should =~
assert_no_match: should.not.match, should.not =~

assert_instance_of: should.be.an.instance_of
assert_kind_of: should.be.a.kind_of
assert_respond_to: should.respond_to

assert_raise: should.raise
assert_nothing_raised: should.not.raise
assert_throws: should.throw
assert_nothing_thrown: should.not.throw
assert_block: should.satisfy

== Additional assertions

These assertions are not included in Test::Unit, but have been added
to test/spec for convenience:

* should.not.satisfy
* a.should.<predicate> (works like assert a.<predicate>?)
* a.should.be <operator> (where <operator> is <, <=, >, >=, or ===)
* should.output, to check what is printed

== Messaging/Blaming

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
Should#blaming or Should#messaging methods:

    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

A CustomShould by default takes one argument, which is placed in
self.object for your convenience.

You can CustomShould#failure_message to provide a better error
message.

== 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 --runner=specdox (or -rs) looks like RSpec's output:

    spec.output
    - works for print
    - works for puts
    - works with readline

RDox, run with --runner=rdox (or -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

== Disabled specifications

Akin to the usual Test::Unit practice, tests quickly can be disabled
by replacing specify with xspecify. test/spec will count the
disabled tests when you run it with SpecDox or RDox.

== specrb

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

See specrb --help for the usage.

== Changes in version 0.3

  * should.be_close, should.be_an_instance_of, should.be_a_kind_of,
    and should.be_nil have been deprecated. Use the dot-variants of
    them. These assertions will be removed in 1.0.
  * specrb -a now includes -Ilib by 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

== Roadmap

Version 1.0 (February 2006):: first stable release.

== Contact

Please mail bugs, suggestions and patches to
<mailto:chneukirchen@gmail.com>.

Darcs repository ("darcs send" is welcome for patches):
http://chneukirchen.org/repos/testspec

== Thanks to

* 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.

== Copying

Copyright (C) 2006, 2007 Christian Neukirchen <http://purl.org/net/chneukirchen>
test/spec is licensed under the same terms as Ruby itself.

== Where can I get it?

You can download test/spec 0.3 at

        http://chneukirchen.org/releases/test-spec-0.3.0.tar.gz

Alternatively, you can checkout from the development repository with:

           darcs get http://chneukirchen.org/repos/testspec

(Patches using "darcs send" are most welcome.)

== Links

Behavior-Driven Development:: <http://behaviour-driven.org/>
RSpec:: <http://rspec.rubyforge.org/>
script.aculo.us testing:: <http://mir.aculo.us/articles/2006/08/29/bdd-style-javascript-testing>
FlexMock:: <http://onestepback.org/software/flexmock/>
Mocha:: <http://mocha.rubyforge.org/>

Happy hacking and have a nice day,

···

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

ea043ab5837994179d4659aa1e2fcc88 test-spec-0.3.0.tar.gz
d0e1c45c2e814cc26a7967232ca99f6c test-spec-0.3.0.gem

Christian Neukirchen wrote:
...

test/spec does not include a mocking/stubbing-framework; use whichever
you like to---FlexMock and Mocha have been tested.

test/spec has no dependencies outside Ruby 1.8.

The test-spec gem does seem to depend on both FlexMock and Mocha. Not complaining, I would have grabbed them anyway.

···

--
        vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Both of which (for me at least) had to be installed before test/spec:

[1807] sudo gem update
Updating installed gems...
Need to update 18 gems from http://gems.rubyforge.org
..................
complete
Gems: updated
[1808] sudo gem install test-spec --source
Index of /releases/gems/
Install required dependency flexmock? [Yn]
ERROR: While executing gem ... (Gem::GemNotFoundException)
    Could not find flexmock (>= 0.4.1) in the repository

YMMV

Allan

···

On 24 Jan, 21:29, Joel VanderWerf <v...@path.berkeley.edu> wrote:

Christian Neukirchen wrote:..

> test/spec has no dependencies outside Ruby 1.8.

The test-spec gem does seem to depend on both FlexMock and Mocha. Not
complaining, I would have grabbed them anyway.

Joel VanderWerf <vjoel@path.berkeley.edu> writes:

Christian Neukirchen wrote:
...

test/spec does not include a mocking/stubbing-framework; use whichever
you like to---FlexMock and Mocha have been tested.
test/spec has no dependencies outside Ruby 1.8.

The test-spec gem does seem to depend on both FlexMock and Mocha. Not
complaining, I would have grabbed them anyway.

That (optional) dependency will be removed in the next release.

···

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Allan wrote:

Christian Neukirchen wrote:..

test/spec has no dependencies outside Ruby 1.8.

The test-spec gem does seem to depend on both FlexMock and Mocha. Not
complaining, I would have grabbed them anyway.

Both of which (for me at least) had to be installed before test/spec:

[1807] sudo gem update
Updating installed gems...
Need to update 18 gems from http://gems.rubyforge.org
..................
complete
Gems: updated
[1808] sudo gem install test-spec --source
Index of /releases/gems/
Install required dependency flexmock? [Yn]
ERROR: While executing gem ... (Gem::GemNotFoundException)
    Could not find flexmock (>= 0.4.1) in the repository

That's odd. I installed from the default source, and said "Y" to both dependencies, and it worked.

Maybe in your case it was looking for flexmock in the chneukirchen.org source?

···

On 24 Jan, 21:29, Joel VanderWerf <v...@path.berkeley.edu> wrote:

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407