Credit: Steve Arneil
You want to run some or all of the unit tests youve written.
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
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
Strings
Numbers
Date and Time
Arrays
Hashes
Files and Directories
Code Blocks and Iteration
Objects and Classes8
Modules and Namespaces
Reflection and Metaprogramming
XML and HTML
Graphics and Other File Formats
Databases and Persistence
Internet Services
Web Development Ruby on Rails
Web Services and Distributed Programming
Testing, Debugging, Optimizing, and Documenting
Packaging and Distributing Software
Automating Tasks with Rake
Multitasking and Multithreading
User Interface
Extending Ruby with Other Languages
System Administration