Verifying methods using rubycheck

Written by Ben Wendt

rubycheck is a library implementing similar functionality to the quickcheck library in haskell. Using rubycheck, you can write assertions that a method works for all given inputs meeting a given criteria. Of course, the implementation is to just try a bunch of options and see whether they all meet the desired outcome. Using rubycheck gives you the power to verify your code works for a wider variety of cases than you might normally put into a unit test (or at least lets you hide the random input generator within a gem).

A standard example would be to do something like this:

> proposition = -> a { reverser(reverser(a) }

> RubyCheck.for_all(proposition, [:gen_str])
# true

Here’s a more detailed example using rspec to run the test:

# a contrived example class
class Adder
  def self.add(a, b)
    if a > 0
      a + b
    else
      -a + b
    end
  end
end

This class will take the absolute value of the first input, then add to the second. So we can make an assertion that the result of adding a negative number to a positive number will be different than if we added the numbers using standard addition. Let’s see what that assertion would look like.

Your spec/adder_spec.rb:

describe Adder, '#add' do
  it 'is performs addition' do
    prop_add = -> a { Adder.add(a, 5) == a + 5 }
    prop_neg_add = -> a { Adder.add(-a, 5) == a + 5 }

    expect(RubyCheck.for_all(prop_add, [:gen_int])).not_to(equal(true))

    expect(RubyCheck.for_all(prop_neg_add, [:gen_uint])).to(equal(true))
    expect(RubyCheck.for_all(prop_add, [:gen_uint])).to(equal(true))
  end

end

And that’s it. With that little bit of code you can sleep a little easier at night, knowing that you have a test that checks your code with a wider range of inputs than you might otherwise have written.