Running Unit Tests
Credit: Steve Arneil
Problem
You want to run some or all of the unit tests youve written.
Solution
This solution uses the example test class PersonTest from the previous recipe, Recipe 17.7. In that scenario, this code lives in a file test/person_test.rb, and the code to be tested lives in app/person.rb. Heres test/person_test.rb again:
# person_test.rb require File.join(File.dirname(__FILE__), .., app, person) require est/unit class PersonTest < Test::Unit::TestCase FIRST_NAME, LAST_NAME, AGE = Nathaniel, Talbott, 25 def setup @person = Person.new(FIRST_NAME, LAST_NAME, AGE) end def test_first_name assert_equal FIRST_NAME, @person.first_name end def test_last_name assert_equal LAST_NAME, @person.last_name end def test_full_name assert_equal FIRST_NAME + + LAST_NAME, @person.full_name end def test_age assert_equal 25, @person.age assert_raise(ArgumentError) { Person.new(FIRST_NAME, LAST_NAME, -4) } assert_raise(ArgumentError) { Person.new(FIRST_NAME, LAST_NAME, four) } end end
As seen in the previous recipe, the simplest solution is to run the script that contains the tests as a Ruby script:
$ ruby test/person_test.rb Loaded suite test/person_test Started …. Finished in 0.008955 seconds. 4 tests, 6 assertions, 0 failures, 0 errors
But the person_test.rb script also accepts command-line arguments. You can use the --name option to choose which test methods to run, and the --verbose option to print each test method as its run:
$ ruby test/person_test.rb --verbose --name test_first_name --name test_last_name Loaded suite test/person_test Started test_first_name(PersonTest): . test_last_name(PersonTest): . Finished in 0.012567 seconds. 2 tests, 2 assertions, 0 failures, 0 errors
Discussion
How do the tests run when person_test.rb doesn appear to do anything but define a class? How can person_test.rb accept command-line arguments? We wrote that file, and we didn put in any command-line parsing code.
It all happens behind the scenes. When we required the Test::Unit framework, it passed a block into the method method Kernel#at_exit. This block is guaranteed to be called before the Ruby interpreter exits. It looks like this:
$ tail -5 /usr/local/lib/ruby/1.8/test/unit.rb at_exit do unless $! || Test::Unit.run? exit Test::Unit::AutoRunner.run end end
Once the code in person_test.rb defines its test class, the Ruby interpreter exits: but first, it runs that block, which triggers the AutoRunner test runner. This does the command-line parsing, the execution of the tests in PersonTest, and all the rest of it.
Here are a few more helpful options to a unit test script.
The --name option can be used with a regular expression to choose the test methods to run.
$ ruby test/person_test.rb --verbose --name /test_f/ Loaded suite test/person_test Started test_first_name(PersonTest): . test_full_name(PersonTest): . Finished in 0.014891 seconds. 2 tests, 2 assertions, 0 failures, 0 errors
The Test::Unit framework can be also be loaded alone to run tests in the current directory and its subdirectories. Use the --pattern option with a regular expression to select the test files to run:
$ ruby -rtest/unit -e0 -- --pattern /_test/ Loaded suite . Started … Finished in 0.009329 seconds. 4 tests, 6 assertions, 0 failures, 0 errors
To list all the available Test::Unit options, use the --help option:
$ ruby test/person_test.rb --help
Additional options are available when the Test::Unit framework is run standalone. Again, use the --help option:
$ ruby -rtest/unit -e0 -- --help
See Also
- ri Test::Unit
- Recipe 15.22, "Unit Testing Your Web Site"
- Recipe 17.7, "Writing Unit Tests"
- Recipe 19.1, "Automatically Running Unit Tests"
Категории