2. Introducing Test/Unit
2.1. The Small Picture
2.1.1. Hello World
As we all know, Ruby ships with a boat load of great libraries. If you're like me, you've only used a quarter of them or so. One little gem of a library is test/unit. It comes packaged with Ruby 1.8.1, so there's nothing to download.
By using one line of code require 'test/unit', you arm your Ruby script with the capability to write tests.
Let's show you a really basic test, and then we'll step through it and explain some details.
# hello_test.rb require 'test/unit' class HelloTestCase < Test::Unit::TestCase def test_hello assert true end end
Quite possibly the simplest and least useful test ever invented, but it shows you the bare bones of writing a test case. That script can be run from the command line the same way your run any other Ruby script.
Simply run ruby hello_test.rb and you will see the following:
Started . Finished in 0.0 seconds. 1 tests, 1 assertions, 0 failures, 0 errors
Congratulations, your first test.
2.1.2. What Does It All Mean?
By looking at the output of a test, you will be able to tell if the tests pass or not. In our example, not surprisingly, we've passed. The summary shows 1 test, 1 assertion, 0 failures, and 0 errors.
So, let's break our test source code down.
First, line 1.
require 'test/unit'
You'll always have this when writing unit tests. It contains the classes and functionality to write and run unit tests.
Next, we have a class HelloTestCase which derives from Test::Unit::TestCase.
class HelloTestCase < Test::Unit::TestCase
All of the tests that you create will directly subclass Test::Unit::TestCase. The TestCase provides the “housing” of where your tests will live. More on this in a bit.
Finally, we have a method called test_hello.
def test_hello
All tests must follow this naming convention: their names start with the first 4 characters test, as in test_hello, testme, and testarosa. If you create a method that doesn't start with test, the testing framework won't recognize it as a test, hence, won't run it automatically, hence it is a normal Ruby method.
Inside our test_hello method, we have an assertion.
assert true
Assertions are where the real work gets done. There are a whole army of different types of assertions that you'll use to make sure your code is doing the right thing.
2.2. The Big Picture
Grab a cup of coffee and dunk your head in some ice water, because here's some more theory.
There are 4 major players in the testing game.
2.2.1. A: The Assertion
An Assertion is 1 line of code that evaluates an object (or expression) for expected results.
For example, is this value = that value? is this object nil? does this line of code throw an exception? is the user's password greater than 5 characters?
2.2.2. B: The Test
A Test is method that contains assertions which represent a particular testing scenario.
For example, we may have a test method called test_valid_password. In order for this test to pass, we might need to check a few things:
-
password is 4 or more characters
-
password isn't the word ‘password'
-
password isn't all spaces
If all of these assertions are successful, the test will pass.
2.2.3. C: The Test Case
A Test Case is a class inherited from Test::Unit::TestCase containing a testing “strategy” comprised of contextually related tests.
For example, I may have a test case called UserTestCase which has a bunch of tests that check that:
-
the password is valid (test_password)
-
the username doesn't have any forbidden words (test_username_cussin)
-
a user is under the age of 150 (test_shriveled_raisin)
2.2.4. D: The Test Suite
A Test Suite is a collection of test cases. When you run a test suite, it will, in turn, execute each test that belongs to it.
For example, instead of running each test unit individually, you can run them all by creating a suite and including them. This is good for stuff like continuous-build integration.
We won't get into test suites in this article.
2.2.5. The Hierarchy
The relationship of these objects to one-another looks like this:
-
a test suite
-
has many test cases
-
which have many tests
-
which have many assertions
