# Ruby Programming/Unit testing

← Exceptions | RubyDoc →
Unit testing is a great way to catch errors early in the development process, if you dedicate time to writing appropriate and useful tests. As in other languages, Ruby provides a framework in its standard library for setting up, organizing, and running tests called Test::Unit.
There are other very popular testing frameworks, rspec and cucumber come to mind.
Specifically, Test::Unit provides three basic functionalities:
* A way to define basic pass/fail tests.
* A way to gather related tests together and run them as a group.
* Tools for running single tests or whole groups of tests.

## A Simple Introduction

First create a new class.
Let's start with an example to test the SimpleNumber class.
Which produces
So what happened here? We defined a class TestSimpleNumber which inherited from Test::Unit::TestCase. In TestSimpleNumber we defined a member function called test_simple. That member function contains a number of simple assertions which exercise my class. When we run that class (note I haven't put any sort of wrapper code around it -- it's just a class definition), the tests are automatically run, and we're informed that we've run 1 test and 2 assertions.
Let's try a more complicated example.
Now there are three tests (three member functions) in the class. The function test_typecheck uses assert_raise to check for an exception. The function test_failure is set up to fail, which the Ruby output happily points out, not only telling us which test failed, but how it failed (expected <3> but was <4>). On this assertion, we've also added an final parameters which is a custom error message. It's strictly optional but can be helpful for debugging. All of the assertions include their own error messages which are usually sufficient for simple debugging.

## Available Assertions

Test::Unit provides a rich set of assertions, which are documented thoroughly at Ruby-Doc. Here's a brief synopsis (assertions and their negative are grouped together. The text description is usually for the first one listed -- the names should make some logical sense):
| assert( boolean, [message] ) | True if boolean |
| assert_equal( expected, actual, [message] ) assert_not_equal( expected, actual, [message] ) | True if expected == actual |
| assert_match( pattern, string, [message] ) assert_no_match( pattern, string, [message] ) | True if string =~ pattern |
| assert_nil( object, [message] ) assert_not_nil( object, [message] ) | True if object == nil |
| assert_in_delta( expected_float, actual_float, delta, [message] ) | True if (actual_float - expected_float).abs <= delta |
| assert_instance_of( class, object, [message] ) | True if object.class == class |
| assert_kind_of( class, object, [message] ) | True if object.kind_of?(class) |
| assert_same( expected, actual, [message]) assert_not_same( expected, actual, [message] ) | True if actual.equal?( expected ). |
| assert_raise( Exception,... ) {block} assert_nothing_raised( Exception,...) {block} | True if the block raises (or doesn't) one of the listed exceptions. |
| assert_throws( expected_symbol, [message] ) {block} assert_nothing_thrown( [message] ) {block} | True if the block throws (or doesn't) the expected_symbol. |
| assert_respond_to( object, method, [message] ) | True if the object can respond to the given method. |
| assert_send( send_array, [message] ) | True if the method sent to the object with the given arguments return true. |
| assert_operator( object1, operator, object2, [message] ) | Compares the two objects with the given operator, passes if true |

## Structuring and Organizing Tests

Tests for a particular unit of code are grouped together into a test case, which is a subclass of Test::Unit::TestCase. Assertions are gathered in tests, member functions for the test case whose names start with test_. When the test case is executed or required, Test::Unit will iterate through all of the tests (finding all of the member functions which start with test_ using reflection) in the test case, and provide the appropriate feedback.
Test case classes can be gathered together into test suites which are Ruby files which require other test cases:
In this way, related test cases can be naturally grouped. Further, test suites can contain other test suites, allowing the construction of a hierarchy of tests.
This structure provides relatively fine-grained control over testing. Individual tests can be run from a test case (see below), a full test case can be run stand-alone, a test suite containing multiple cases can be run, or a suite of suites can run, spanning many test cases.

### Naming Conventions

The author of Test::Unit, Nathaniel Talbott, suggests starting the names of test cases with tc_ and the names of test suites with ts_

### Running Specific Tests

It's possible to run just one (or more) tests out of a full test case:
It is also possible to run all tests whose names match a given pattern:

### Setup and Teardown

There are many cases where a small bit of code needs to be run before and/or after each test. Test::Unit provides the setup and teardown member functions, which are run before and after every test (member function).

## Exercises
### Radius of a bike tire

Implement a class with a public method that can solve the following problem: A user has a rubber bicycle tire of an arbitrary circumference. When one side is cut, and the bike tire is stretched into a line, it is measured at an arbitrary length. From this length, determine the radius of the bike tire originally.
After this, write a test case to test the class. It should include at least 2 methods to test.

## External Links

* Test::Unit documentation at Ruby-Doc