Test Bench offers a fairly simple but flexible implementation of assert
. The easiest way to use assert
is to simply pass it a single positional parameter that you expect won’t be nil
or false
:
assert x == y
assert x > y
assert x.some_method(:some_argument)
This is enough to get started. There are no elaborate matchers or assertion methods that print out exactly what went wrong (see Rationale). However, assertions can be made more powerful through assert’s block form syntax and assertion modules.
It is common to assert that something is not "truthy"; in such cases, assert !subject
is certainly viable, if slightly cryptic. To improve readability in these circumstances, refute
is offered as the negated complement of assert
:
refute false
refute nil
refute x == y
assert
takes an optional block which, when supplied, changes the way assert
operates. Without a block, assert
simply expects the value passed in to be "truthy." When a block is passed, the block is evaluated, and its result is then expected to be "truthy." The argument passed to assert is then passed to the block:
assert "Some test subject" do |subject|
subject == "Some test subject"
end
The argument subject
is actually optional; the block is evaluated in the instance context of the test subject, so the above can be rewritten like this:
assert "Some test subject" do
self == "Some test subject"
end
In this way, you can pass the test subject itself into assert
:
test "Any number plus zero equals the number" do
number = 42
assert number do
(self + 0) == num
end
end
In some cases, the block form syntax will help make the test clearer by separating the test subject from the assertion itself. In other cases, it will add unnecessary confusion. Be tasteful.
You can extend the test subject with predicate methods useful specific for assertions by passing a Module
as the second argument to assert
. Those methods are then available within the supplied block. For instance, suppose you want to test that a particular piece of text was written to a file. Your could define a module that implements a written?
predicate, and pass that into assert
:
module WrittenPredicate
def written?(expected_text)
self.rewind
actual_text = read
actual_text == expected_text
end
end
test "File can be written to" do
file = Tempfile.new
file.write "Some text"
assert file, WrittenPredicate do
written? "Some text"
end
end
You can actually place modules named Assertions
within the namespace of your classes and modules, and Test Bench will detect their presence automatically and extend
the modules onto the subject for you! Here is an example, where a done?
predicate is defined in an Assertions
module for SomeClass
, and then later used to test an instance of SomeClass
:
class SomeClass
def do_it
@done = true
end
module Assertions
def done?
@done
end
end
end
test "Some class" do
object = SomeClass.new
object.do_it
assert object do
done?
end
end
Tip
|
The above assertion can be further shortened via Symbol#to_proc : assert object, &:done?
|
It is recommended to ship assertion modules with your classes and modules wherever possible. They are conceptually similar to matchers in RSpec, or assertion in Minitest/test/unit
, but they keep the code specific to a particular class with the namespace of that particular class. In other test frameworks, all the special code to test particular types of objects ends up lumped together with all the other special code for testing other types of objects; this is a cohesion problem. With Test Bench, design principles apply equally to test code.
Now that assertion modules are clear, the approach for testing errors using Test Bench can be demonstrated. Test Bench actually provides an assertion module for Proc
which defines a predicate method, raises_error?
. This method can accept an optional argument that, when specified, corresponds to the exact class you are expecting the Proc
to raise. If no argument is specified, then the predicate method returns true if any exception of type StandardError
or its descendants is raised.
test "Expect a particular error type to be raised" do
assert proc { nil.some_method } do
raises_error? NoMethodError
end
end
test "Expect any error type to be raised" do
assert proc { nil.some_method } do
raises_error?
end
end
Next: Output