RushCheck
a lightweight random testing tool for Ruby

Combine another testing frameworks and RushCheck

(2006/10/08)

In this article, I will introduce how to combine Ruby’s unit testing ‘test/unit’ and RushCheck. I have also tried RSpec which supports BDD (Behaviour Driven Development) style checking specifications.

To watch the testing code, we need a target of tests. I quote the following simple example from the tutorial of RSpec.

# stack.rb
class Stack
  def initialize
    @stack = []
  end

  def empty?
    @stack.empty?
  end

  def push(item)
    @stack.push item
  end
end

This class Stack is not implemented fully, and it’s only a subset of Array, but don’t mind.

To test the Stack with ‘test/unit’, we have to write testing codes. Here is an usual unit test cases without RushCheck:

# test_stack.rb
require 'test/unit'
require 'stack'

class TC_Stack < Test::Unit::TestCase

  def test_empty_stack
    stack = Stack.new
    assert stack.empty?
  end

  def test_not_empty_after_push
    stack = Stack.new
    stack.push 1
    assert(! stack.empty?)
  end

end
The result of the above test codes:
% ruby test_stack.rb
Loaded suite test_stack
Started
..
Finished in 0.004112 seconds.

2 tests, 2 assertions, 0 failures, 0 errors

Because testcases are too small, it takes only 0.004112 seconds. However, if we are not satisfied that the code tested only one case ‘stack.push 1’, then we can apply RushCheck to it.

begin
  require 'rubygems'
  require_gem 'rushcheck'
rescue LoadError
  require 'rushcheck'
end

def forall(*cs, &f)
  assert(RushCheck::Claim.new(*cs, &f).check)
end

require 'test/unit'
require 'stack'

class TC_Stack < Test::Unit::TestCase

  def test_empty_stack
    stack = Stack.new
    assert stack.empty?
  end

  def test_not_empty_after_push
    stack = Stack.new
    forall(Integer) do |item|
      stack.push item
      assert(! stack.empty?)
    end
  end

end

The difference between two test codes are: (1) require ‘rushcheck’ (2) define ‘forall’ (3) test many cases with the forall method.

Results:
Loaded suite test_stack
Started
.OK, passed 100 tests.
2 tests, 101 assertions, 0 failures, 0 errors

The above result shows that just 100 assertions are tested in the second case and the total time takes 0.185286 seconds. Of course it is longer than the first example, but still less than 1 seconds.

The ‘forall’ method is a sugar, i mean it is an alias of RushCheck::Claim.new, and make the code easy to read.

I’m satisfied that after combining unit tests and random tests, we get usuful automatic testing in lightweight way.

However, I heard more nicer testing framework from IRC #ruby-lang@freenode channel (thanks to all), called RSpec. It’s installable with RubyGems in a moment, like
% sudo gem install rspec

The BDD-style testing code is more readable than unit testing code. Here is another testing code with RSpec and without RushCheck:

# stack_spec.rb
require 'stack'

context "A new stack" do
  setup do
    @stack = Stack.new
  end
  specify "should be empty" do
    @stack.should_be_empty
  end
end

context "An empty stack" do
  setup do
    @stack = Stack.new
  end
  specify "should not be empty after 'push'" do
    @stack.push 1
    @stack.should_not_be_empty
  end
end

The code looks like an English phrases. Excellent. To check, say in BDD-style we use ‘check’ instead ‘test’, we use the ‘spec’ command which is distributed by RSpec module.

% spec stack_spec.rb -f s

A new stack
- should be empty

An empty stack
- should not be empty after 'push'

Finished in 0.007394 seconds

2 specifications, 0 failures

The above results of checking specifications are also well-formated! In my opinion, the advantages of RSpec are (1) readable testing code (not testing but checking specifications) (2) also readable outputs (3) lightweight implementation based on test/unit.

As we have seen, we can combine RSpec and Rushcheck in the same way for unit testing. Here is the last code snippet in this article.
# stack_spec.rb
begin
  require 'rubygems'
  require_gem 'rushcheck'
rescue LoadError
  require 'rushcheck'
end

require 'stack'

def forall(*cs, &f)
  RushCheck::Claim.new(*cs, &f).check.should_equal true
end

require 'stack'

context "A new stack" do
  setup do
    @stack = Stack.new
  end
  specify "should be empty" do
    @stack.should_be_empty
  end
end

context "An empty stack" do
  setup do
    @stack = Stack.new
  end
  specify "should not be empty after 'push'" do
    forall(Integer) do |item|
      @stack.push item
      @stack.should_not_be_empty
    end
  end
end
% spec stack_spec.rb -f s
A new stack
- should be empty

An empty stack
OK, passed 100 tests.
- should not be empty after 'push'

Finished in 0.211421 seconds

2 specifications, 0 failures

See also ‘data/examples/rspec’ in the distribution for details.

Note: The ‘forall’ trick is not enabled until ver 0.5. Please install the current release of RushCheck if you have old one. At the current release (ver 0.6), the restriction about the number of arguments of Assertion.new is deleted for this trick at unit testing.


Written by Daisuke IKEGAMI
Full of CC licensed ripley's debris
HTML and CSS Design by Nicolas Fafchamps
Generated with Rote and Rog