Automatically Running Unit Tests

Credit: Pat Eyler

Problem

You want to make it easy to run your projects unit test suite. You also want the tests to run automatically before you do a new release of your project.

Solution

Require the rake/testtask library and create a new Rake::TestTask. Save the following code in a file called Rakefile in the projects top-level directory (or add it to your existing Rakefile).

	require  
rake/testtask

	Rake::TestTask.new(	est) do |t|
	 t.pattern = 	est/**/tc_*.rb
	 t.warning = true
	end

This Rakefile makes two assumptions:

  1. The Test::Unit test cases live in files under the test directory (and its subdirectories). The names of these files start with tc_ and end in .rb.

  2. The Ruby libraries to be tested live under the lib directory. Rake automatically appends this directoy to Rubys load path, the list of directories that Ruby searches when you try to require a library.

To execute your test cases, run the command rake test in the projects top-level directory. The tests are loaded by a new Ruby interpreter with warnings enabled. The output is the same as youd see from Test::Units console runner.

Discussion

If its easy to trigger the test process, youll run your tests more often, and youll detect problems sooner. Rake makes it really convenient to run your tests.

We can make the test command even shorter by defining a default task. Just add the following line to the Rakefile. The position within the file doesn matter, but to keep things clear, you should put it before other task definitions:

	task "default" => ["test"]

Now, whenever we run rake without an argument, it will invoke the test task. If your Rakefile already has a default task, you should be able to just add the test task to its list of prerequisites. Similarly, if you have a task that packages a new release of your software (like the one defined in Recipe 19.4), you can make the test task a prerequisite. If your tests fail, your package won be built and you won release a buggy piece of software.

The Rake::TestTask has a special attribute, libs; the entries in this array are added to Rubys load path. As mentioned above, the default value is ["lib"], making it possible for your tests to require files in your projects lib/ subdirectory. Sometimes this default is not enough. Your Ruby code might not be in the lib/ subdirectory. Or worse, your test code might change the current working directory. Since lib/ is a relative path, the default value of libs would start out as a valid source for library files, and then stop being valid when the test code changed the working directory.

We can solve this problem by specifying the absolute path to the projects lib directory in the Rakefile. Using an absolute path is generally more stable. In this sample Rakefile, we give the load path the absolute path to the lib and test subdirectories. Adding the test directory to the load path is useful if you need to require a library full of test utility methods:

	require  
rake/testtask

	lib_dir = File.expand_path(lib)
	test_dir = File.expand_path(	est)

	Rake::TestTask.new("test") do |t|
	 t.libs = [lib_dir, test_dir]
	 t.pattern = "test/**/tc_*.rb"
	 t.warning = true
	end

Test suites

As a project grows, it takes longer and longer to run all the test cases. This is bad for the habit we e trying to inculcate, where you run the tests whenever you make a change. To solve this problem, group the test cases into test suites. Depending on the project, you might have a test suite of all test cases concerning file I/O, another suite for the console interface, and so on.

Lets say that when you e working on the DataFile class, you can get away with only running the file I/O test suite. But before releasing a new version of the software, you need to run all the test cases.

To create a Rake test suite, instantiate a Rake::TestTask instance, and set the test_files attribute to something other than the complete list of test files. This sample Rakefile splits up the test files into two suites.

	require  
rake/testtask

	Rake::TestTask.new(	est-file) do |t|
	 t.test_files = [	est/tc_datafile.rb,
	 	est/tc_datafilewriter.rb,
	 	est/tc_datafilereader.rb]
	 t.warning = true
	end

	 
Rake::TestTask.new(	est-console) do |t|
	 t.test_files = [	est/tc_console.rb,
	 	est/tc_prettyprinter.rb]
	 t.warning = true
	end

Invoking rake test-file runs the tests related to file I/O, and invoking rake test-console tests the console interface. The only thing missing is a task that runs all tests. You can either use the all-inclusive task from the Rakefile given in the Solution, or you can create a task that has all the test suites as prerequisites:

	task 	est => [	est-file, 	est-console]

When this test task is invoked, Rake runs the test-file suite and then the test-console suite. Each suite is run in its own Ruby interpreter.

See Also

  • Recipe 17.8, "Running Unit Tests"
  • For a guide to the options available to the TestTask class, consult its RDoc; its available at, for instance, http://rake.rubyforge.org/classes/Rake/TestTask.html


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



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net