Centralizing the Creation of Objects Common to Test Cases

Problem

A test case contains a series of individual tests. It's not uncommon for these tests to share common objects or resources. Instead of initializing an object for each test method, you want to do it only once per test case. For example, you might have an application that writes report data to files, and your test methods each need to open a file object to operate on.

Solution

Use the setup and teardown methods to put code that should be run before and after each individual test in your test case. To make a file available for writing by the tests in the ReportTest class, define the following setup and teardown methods:

test/unit/report_test.rb:

require File.dirname(__FILE__) + '/../test_helper'
class ReportTest < Test::Unit::TestCase
 def setup
 full_path = "#{RAILS_ROOT}/public/reports/"
 @report_file = full_path + 'totals.csv'
 FileUtils.mkpath(full_path)
 FileUtils.touch(@report_file)
 end
 def teardown
 File.unlink(@report_file) if File.exist?(@report_file)
 end
 def test_write_report_first
 f = File.open(@report_file,"w")
 assert_not_nil f
 assert f.syswrite("test output"), "Couldn't write to file"
 assert File.exist?(@report_file)
 end
 def test_write_report_second
 f = File.open(@report_file,"w")
 assert f.syswrite("more test output..."), "Couldn't write to file"
 end end

Discussion

The setup method in the solution creates a directory and a file within that directory called totals.csv. The teardown method removes the file. A new version of totals.csv is created for each test method in the test case, so each of the two test methods writes its output to its own version of totals.csv. The execution plan is:

  1. setup

  2. test_write_report_first

  3. teardown

  4. setup

  5. test_write_report_second

  6. teardown

The teardown method is for any cleanup of resources you may want to do, such as closing network connections. It's common to use a setup method without a corresponding teardown method when no explicit cleanup is necessary. In this case, deleting the file is necessary if you're going to eliminate dependencies between tests: each test should start with an empty file.