* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / lib / test / unit / testcase.rb
blob3cf80d2256e4dc548a2028538ce98963831fa24c
1 #--
3 # Author:: Nathaniel Talbott.
4 # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
5 # License:: Ruby license.
7 require 'test/unit/assertions'
8 require 'test/unit/failure'
9 require 'test/unit/error'
10 require 'test/unit/testsuite'
11 require 'test/unit/assertionfailederror'
12 require 'test/unit/util/backtracefilter'
14 module Test
15   module Unit
17     # Ties everything together. If you subclass and add your own
18     # test methods, it takes care of making them into tests and
19     # wrapping those tests into a suite. It also does the
20     # nitty-gritty of actually running an individual test and
21     # collecting its results into a Test::Unit::TestResult object.
22     class TestCase
23       include Assertions
24       include Util::BacktraceFilter
25       
26       attr_reader :method_name
27       
28       STARTED = name + "::STARTED"
29       FINISHED = name + "::FINISHED"
31       ##
32       # These exceptions are not caught by #run.
34       PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
35                                 SystemExit]
37       DECENDANT_CLASSES = []
38       def self.inherited(decendant)
39         DECENDANT_CLASSES << decendant
40       end
42       # Creates a new instance of the fixture for running the
43       # test represented by test_method_name.
44       def initialize(test_method_name)
45         unless(respond_to?(test_method_name) && method(test_method_name).arity == 0)
46           throw :invalid_test
47         end
48         @method_name = test_method_name
49         @test_passed = true
50       end
52       # Rolls up all of the test* methods in the fixture into
53       # one suite, creating a new instance of the fixture for
54       # each method.
55       def self.suite
56         method_names = public_instance_methods(true).map { |m| m.to_s }
57         tests = method_names.delete_if {|method_name| method_name !~ /^test./}
58         suite = TestSuite.new(name)
59         tests.sort.each do
60           |test|
61           catch(:invalid_test) do
62             suite << new(test)
63           end
64         end
65         if (suite.empty?)
66           catch(:invalid_test) do
67             suite << new(:default_test)
68           end
69         end
70         return suite
71       end
73       # Runs the individual test method represented by this
74       # instance of the fixture, collecting statistics, failures
75       # and errors in result.
76       def run(result)
77         yield(STARTED, name)
78         @_result = result
79         begin
80           setup
81           __send__(@method_name)
82         rescue AssertionFailedError => e
83           add_failure(e.message, e.backtrace)
84         rescue Exception
85           raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
86           add_error($!)
87         ensure
88           begin
89             teardown
90           rescue AssertionFailedError => e
91             add_failure(e.message, e.backtrace)
92           rescue Exception
93             raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
94             add_error($!)
95           end
96         end
97         result.add_run
98         yield(FINISHED, name)
99       end
101       # Called before every test method runs. Can be used
102       # to set up fixture information.
103       def setup
104       end
106       # Called after every test method runs. Can be used to tear
107       # down fixture information.
108       def teardown
109       end
110       
111       def default_test
112         flunk("No tests were specified")
113       end
115       # Returns whether this individual test passed or
116       # not. Primarily for use in teardown so that artifacts
117       # can be left behind if the test fails.
118       def passed?
119         return @test_passed
120       end
121       private :passed?
123       def size # :nodoc:
124         1
125       end
127       def add_assertion # :nodoc:
128         @_result.add_assertion
129       end
130       private :add_assertion
132       def add_failure(message, all_locations=caller()) # :nodoc:
133         @test_passed = false
134         @_result.add_failure(Failure.new(name, filter_backtrace(all_locations), message))
135       end
136       private :add_failure
138       def add_error(exception) # :nodoc:
139         @test_passed = false
140         @_result.add_error(Error.new(name, exception))
141       end
142       private :add_error
144       # Returns a human-readable name for the specific test that
145       # this instance of TestCase represents.
146       def name
147         "#{@method_name}(#{self.class.name})"
148       end
150       # Overridden to return #name.
151       def to_s
152         name
153       end
154       
155       # It's handy to be able to compare TestCase instances.
156       def ==(other)
157         return false unless(other.kind_of?(self.class))
158         return false unless(@method_name == other.method_name)
159         self.class == other.class
160       end
161     end
162   end