class Test::Unit::TestCase
Ties everything together. If you subclass and add your own test methods, it takes care of making them into tests and wrapping those tests into a suite. It also does the nitty-gritty of actually running an individual test and collecting its results into a Test::Unit::TestResult object.
You can run two hooks before/after a TestCase run.
Example:
class TestMyClass < Test::Unit::TestCase class << self def startup ... end def shutdown ... end end def setup ... end def cleanup ... end def teardown ... end def test_my_method1 ... end def test_my_method2 ... end end
Here is a call order:
-
startup
-
setup
-
test_my_method1
-
cleanup
-
teardown
-
setup
-
test_my_method2
-
cleanup
-
teardown
-
shutdown
You can set an attribute to each test.
Example:
class TestMyClass < Test::Unit::TestCase attribute :speed, :fast def test_my_fast_method # You can get the attribute via `self[]` self[:speed] # => :fast ... end attribute :speed, :slow def test_my_slow_method self[:speed] # => :slow ... end end
Attributes
Public Class Methods
Describes a test.
The following example associates “register a normal user” description with “test_register” test.
description "register a normal user" def test_register ... end
# File lib/test/unit/testcase.rb, line 341 def description(value, target=nil) targets = [target].compact attribute(:description, value, {}, *targets) end
# File lib/test/unit/testcase.rb, line 407 def find_locations(query) query_path = query[:path] query_line = query[:line] query_method_name = query[:method_name] available_locations = target_method_locations(query_path) if query_line available_locations = available_locations.sort_by do |location| -location[:line] end available_location = available_locations.find do |location| query_line >= location[:line] end return [] if available_location.nil? return [] if available_location[:test_case] != self available_locations = [available_location] end if query_method_name available_location = available_locations.find do |location| location[:test_case] == self and query_method_name == location[:method_name] end return [] if available_location.nil? available_locations = [available_location] end available_locations end
Creates a new instance of the fixture for running the test represented by test_method_name.
# File lib/test/unit/testcase.rb, line 483 def initialize(test_method_name) @method_name = test_method_name @internal_data = InternalData.new end
Called after every test case runs. Can be used to tear down fixture information used in test case scope.
Here is an example test case:
class TestMyClass < Test::Unit::TestCase class << self def shutdown ... end end def teardown ... end def test_my_class1 ... end def test_my_class2 ... end end
Here is a call order:
-
test_my_class1 (or test_my_class2)
-
teardown
-
test_my_class2 (or test_my_class1)
-
teardown
-
shutdown
Note that you should not assume test order. Tests should be worked in any order.
# File lib/test/unit/testcase.rb, line 254 def shutdown end
Called before every test case runs. Can be used to set up fixture information used in test case scope.
Here is an example test case:
class TestMyClass < Test::Unit::TestCase class << self def startup ... end end def setup ... end def test_my_class1 ... end def test_my_class2 ... end end
Here is a call order:
-
startup
-
setup
-
test_my_class1 (or test_my_class2)
-
setup
-
test_my_class2 (or test_my_class1)
Note that you should not assume test order. Tests should be worked in any order.
# File lib/test/unit/testcase.rb, line 218 def startup end
Defines a sub test case.
This is a syntax sugar. The both of the following codes are the same in meaning:
Standard:
class TestParent < Test::Unit::TestCase class TestChild < self def test_in_child end end end
Syntax sugar:
class TestParent < Test::Unit::TestCase sub_test_case("TestChild") do def test_in_child end end end
The difference of them are the following:
-
Test case created by {sub_test_case} is an anonymous class. So you can't refer the test case by name.
-
The class name of class style must follow constant naming rule in Ruby. But the name of test case created by {sub_test_case} doesn't need to follow the rule. For example, you can use a space in name such as “child test”.
@param name [String] The name of newly created sub test case. @yield
The block is evaluated under the newly created sub test case class context.
@return [Test::Unit::TestCase] Created sub test case class.
# File lib/test/unit/testcase.rb, line 381 def sub_test_case(name, &block) parent_test_case = self sub_test_case = Class.new(self) do singleton_class = class << self; self; end singleton_class.__send__(:define_method, :name) do [parent_test_case.name, name].compact.join("::") end end sub_test_case.class_eval(&block) sub_test_case end
Rolls up all of the test* methods in the fixture into one suite, creating a new instance of the fixture for each method.
# File lib/test/unit/testcase.rb, line 179 def suite suite_creator = TestSuiteCreator.new(self) suite_creator.create end
Defines a test in declarative syntax or marks following method as a test method.
In declarative syntax usage, the following two test definitions are the almost same:
description "register user" def test_register_user ... end test "register user" do ... end
In test method mark usage, the “my_test_method” is treated as a test method:
test def my_test_method assert_equal("call me", ...) end
# File lib/test/unit/testcase.rb, line 304 def test(*test_description_or_targets, &block) if block_given? test_description = test_description_or_targets.first if test_description.nil? raise ArgumentError, "test description is missing" end n_arguments = test_description_or_targets.size if n_arguments > 1 message = "wrong number of arguments (#{n_arguments} for 1)" raise ArgumentError, message end method_name = "test: #{test_description}" description(test_description, method_name) attribute(:test, true, {}, method_name) if block.respond_to?(:source_location) attribute(:source_location, block.source_location, {}, method_name) end define_method(method_name, &block) else targets = test_description_or_targets attribute(:test, true, {}, *targets) targets.each do |target| AutoRunnerLoader.check(self, target) end end end
Checks whether a test that is matched the query is defined.
@option query [String] :path (nil)
the path where a test is defined in.
@option query [Numeric] :line (nil)
the line number where a test is defined at.
@option query [String] :method_name (nil)
the method name for a test.
# File lib/test/unit/testcase.rb, line 402 def test_defined?(query) locations = find_locations(query) not locations.empty? end
Returns the current test order. This returns :alphabetic
by
default.
# File lib/test/unit/testcase.rb, line 261 def test_order ancestors.each do |ancestor| order = @@test_orders[ancestor] return order if order end AVAILABLE_ORDERS.first end
Sets the current test order.
Here are the available order:
- :alphabetic
-
Default. Tests are sorted in alphabetic order.
- :random
-
Tests are sorted in random order.
- :defined
-
Tests are sorted in defined order.
# File lib/test/unit/testcase.rb, line 278 def test_order=(order) @@test_orders[self] = order end
Private Class Methods
@private
# File lib/test/unit/testcase.rb, line 448 def add_method_location(location) @@method_location_mutex.synchronize do method_locations << location end end
@private
# File lib/test/unit/testcase.rb, line 443 def method_locations @@method_locations[self] ||= [] end
@private
# File lib/test/unit/testcase.rb, line 455 def target_method_locations(path) @@method_location_mutex.synchronize do if path.nil? self_location = method_locations.first path = self_location[:path] if self_location end return [] if path.nil? target_locations = [] @@method_locations.each do |test_case, locations| locations.each do |location| absolete_path = File.expand_path(path) location_path = location[:path] location_basename = File.basename(location_path) if location_path == absolete_path or location_basename == path target_locations << location.merge(:test_case => test_case) end end end target_locations end end
Public Instance Methods
It's handy to be able to compare TestCase instances.
# File lib/test/unit/testcase.rb, line 743 def ==(other) return false unless other.kind_of?(self.class) return false unless @method_name == other.method_name return false unless data_label == other.data_label self.class == other.class end
Notify that the test is passed. Normally, it is not needed because run calls it automatically. If you want to override run, it is not a good idea. Please contact test-unit developers. We will help you without your custom run. For example, we may add a new hook in run.
This is a public API for developers who extend test-unit.
@return [void]
# File lib/test/unit/testcase.rb, line 792 def add_pass current_result.add_pass end
Called after every test method runs but the test method isn't marked as 'passed'. Can be used to clean up and/or verify tested condition. e.g. Can be used to verify mock.
You can add additional cleanup tasks by the following code:
class TestMyClass < Test::Unit::TestCase def cleanup ... end cleanup def my_cleanup1 ... end cleanup do ... # cleanup callback1 end cleanup def my_cleanup2 ... end cleanup do ... # cleanup callback2 end def test_my_class ... end end
Here is a call order:
-
test_my_class
-
cleanup callback2
-
my_cleanup2
-
cleanup callback1
-
my_cleanup1
-
cleanup
# File lib/test/unit/testcase.rb, line 642 def cleanup end
Returns test data for the test. If the test isn't associated with any
test data, it returns nil
.
# File lib/test/unit/testcase.rb, line 705 def data @internal_data.test_data end
Returns a label of test data for the test. If the test isn't associated
with any test data, it returns nil
.
# File lib/test/unit/testcase.rb, line 699 def data_label @internal_data.test_data_label end
# File lib/test/unit/testcase.rb, line 688 def default_test flunk("No tests were specified") end
Returns a description for the test. A description will be associated by ::test or ::description.
Returns a name for the test for no description test.
# File lib/test/unit/testcase.rb, line 733 def description self[:description] || name end
Returns elapsed time for the test was ran.
# File lib/test/unit/testcase.rb, line 756 def elapsed_time @internal_data.elapsed_time end
Returns whether the test is interrupted.
# File lib/test/unit/testcase.rb, line 761 def interrupted? @internal_data.interrupted? end
Returns a human-readable name for the specific test that this instance of TestCase represents.
`#local_name` doesn't include class name. `#name` includes class name.
# File lib/test/unit/testcase.rb, line 720 def local_name if @internal_data.have_test_data? "#{@method_name}[#{data_label}]" else @method_name.to_s end end
Returns a human-readable name for the specific test that this instance of TestCase represents.
# File lib/test/unit/testcase.rb, line 711 def name "#{local_name}(#{self.class.name})" end
Returns whether this individual test passed or not. Primarily for use in teardown so that artifacts can be left behind if the test fails.
# File lib/test/unit/testcase.rb, line 768 def passed? @internal_data.passed? end
Notify that a problem is occurred in the test. It means that the test is a failed test. If any failed tests exist in test suites, the test process exits with failure exit status.
This is a public API for developers who extend test-unit.
@return [void]
# File lib/test/unit/testcase.rb, line 779 def problem_occurred @internal_data.problem_occurred end
Runs the individual test method represented by this instance of the fixture, collecting statistics, failures and errors in result.
# File lib/test/unit/testcase.rb, line 510 def run(result) begin @_result = result @internal_data.test_started yield(STARTED, name) yield(STARTED_OBJECT, self) processed_exception_in_setup = false begin catch do |tag| run_setup do begin run_test run_cleanup add_pass rescue Exception @internal_data.interrupted unless handle_exception($!) processed_exception_in_setup = true raise end throw(tag) end end end rescue Exception if processed_exception_in_setup raise else @internal_data.interrupted raise unless handle_exception($!) end ensure begin run_teardown rescue Exception raise unless handle_exception($!) end end @internal_data.test_finished result.add_run yield(FINISHED, name) yield(FINISHED_OBJECT, self) ensure # @_result = nil # For test-spec's after_all :< end end
Called before every test method runs. Can be used to set up fixture information.
You can add additional setup tasks by the following code:
class TestMyClass < Test::Unit::TestCase def setup ... end setup def my_setup1 ... end setup do ... # setup callback1 end setup def my_setup2 ... end setup do ... # setup callback2 end def test_my_class ... end end
Here is a call order:
-
setup
-
my_setup1
-
setup callback1
-
my_setup2
-
setup callback2
-
test_my_class
# File lib/test/unit/testcase.rb, line 597 def setup end
# File lib/test/unit/testcase.rb, line 692 def size 1 end
Returns a Time at the test was started.
# File lib/test/unit/testcase.rb, line 751 def start_time @internal_data.start_time end
Called after every test method runs. Can be used to tear down fixture information.
You can add additional teardown tasks by the following code:
class TestMyClass < Test::Unit::TestCase def teardown ... end teardown def my_teardown1 ... end teardown do ... # teardown callback1 end teardown def my_teardown2 ... end teardown do ... # teardown callback2 end def test_my_class ... end end
Here is a call order:
-
test_my_class
-
teardown callback2
-
my_teardown2
-
teardown callback1
-
my_teardown1
-
teardown
# File lib/test/unit/testcase.rb, line 685 def teardown end
Overridden to return name.
# File lib/test/unit/testcase.rb, line 738 def to_s name end
Private Instance Methods
# File lib/test/unit/testcase.rb, line 833 def add_assertion current_result.add_assertion end
# File lib/test/unit/testcase.rb, line 797 def current_result @_result end
# File lib/test/unit/testcase.rb, line 821 def handle_exception(exception) self.class.exception_handlers.each do |handler| if handler.respond_to?(:call) handled = handler.call(self, exception) else handled = __send__(handler, exception) end return true if handled end false end
# File lib/test/unit/testcase.rb, line 801 def run_test signature = "#{self.class}\##{@method_name}" redefined_info = self[:redefined] if redefined_info notify("<#{signature}> was redefined", :backtrace => redefined_info[:backtrace]) end if @internal_data.have_test_data? test_method = method(@method_name) arity = test_method.arity if arity.zero? __send__(@method_name) else __send__(@method_name, @internal_data.test_data) end else __send__(@method_name) end end