Class: Test::Unit::TestCase
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
|
|
Inherits: | Object |
Defined in: | lib/test/unit/testcase.rb |
Overview
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 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
Constant Summary
-
AVAILABLE_ORDERS =
Internal use only
# File 'lib/test/unit/testcase.rb', line 125[:alphabetic, :random, :defined]
-
DESCENDANTS =
Internal use only
# File 'lib/test/unit/testcase.rb', line 124[]
-
FINISHED =
Internal use only
# File 'lib/test/unit/testcase.rb', line 120name + "::FINISHED"
-
FINISHED_OBJECT =
Internal use only
# File 'lib/test/unit/testcase.rb', line 122name + "::FINISHED::OBJECT"
-
STARTED =
Internal use only
# File 'lib/test/unit/testcase.rb', line 119name + "::STARTED"
-
STARTED_OBJECT =
Internal use only
# File 'lib/test/unit/testcase.rb', line 121name + "::STARTED::OBJECT"
ErrorHandler - Included
NOT_PASS_THROUGH_EXCEPTIONS, NOT_PASS_THROUGH_EXCEPTION_NAMES, PASS_THROUGH_EXCEPTIONS, PASS_THROUGH_EXCEPTION_NAMES
Assertions - Included
Util::BacktraceFilter - Included
POWERASSERT_PREFIX, TESTUNIT_FILE_SEPARATORS, TESTUNIT_PREFIX, TESTUNIT_RB_FILE
Class Attribute Summary
-
.test_order
rw
Returns the current test order.
-
.test_order=(order)
rw
Sets the current test order.
Class Method Summary
-
.description(value, target = nil)
Describes a test.
- .find_locations(query)
-
.new(test_method_name) ⇒ TestCase
constructor
Creates a new instance of the fixture for running the test represented by test_method_name.
-
.shutdown
Called after every test case runs.
-
.startup
Called before every test case runs.
-
.sub_test_case(name) { ... } ⇒ Test::Unit::TestCase
Defines a sub test case.
-
.suite
Rolls up all of the test* methods in the fixture into one suite, creating a new instance of the fixture for each method.
-
.test(*test_description_or_targets, &block)
Defines a test in declarative syntax or marks following method as a test method.
-
.test_defined?(query) ⇒ Boolean
Checks whether a test that is matched the query is defined.
- .added_method_names Internal use only
- .inherited(sub_class) Internal use only
- .method_added(name) Internal use only
- .method_locations private Internal use only Internal use only
- .target_method_locations(path) private Internal use only Internal use only
Instance Attribute Summary
-
#interrupted? ⇒ Boolean
readonly
Returns whether the test is interrupted.
- #method_name readonly
-
#passed? ⇒ Boolean
readonly
Returns whether this individual test passed or not.
-
#valid? ⇒ Boolean
readonly
Internal use only
Returns the test is valid test.
Instance Method Summary
-
#==(other)
It's handy to be able to compare
TestCase
instances. -
#add_pass ⇒ void
Notify that the test is passed.
-
#cleanup
Called after every test method runs but the test method isn't marked as 'passed'.
-
#data_label
Returns a label of test data for the test.
- #default_test
-
#description
Returns a description for the test.
-
#elapsed_time
Returns elapsed time for the test was ran.
-
#local_name
Returns a human-readable name for the specific test that this instance of
TestCase
represents. -
#name
Returns a human-readable name for the specific test that this instance of
TestCase
represents. -
#problem_occurred ⇒ void
Notify that a problem is occurred in the test.
-
#run(result)
Runs the individual test method represented by this instance of the fixture, collecting statistics, failures and errors in result.
-
#setup
Called before every test method runs.
- #size
-
#start_time
Returns a Time at the test was started.
-
#teardown
Called after every test method runs.
-
#to_s
Overridden to return #name.
- #add_assertion private
- #current_result private
- #handle_exception(exception) private
- #run_test private
-
#assign_test_data(label, data)
Internal use only
Assigns test data to the test.
Util::Output - Included
#capture_output | Returns output for standard output and standard error as string. |
Util::BacktraceFilter - Included
Assertions - Included
#add_assertion | Called whenever an assertion is made. |
#assert, | |
#assert_alias_method | Passes if |
#assert_block | The assertion upon which all other assertions are based. |
#assert_boolean | Passes if |
#assert_compare | Passes if expression “ |
#assert_const_defined | Passes if |
#assert_empty | Passes if |
#assert_equal | Passes if |
#assert_fail_assertion | Passes if assertion is failed in block. |
#assert_false | Passes if |
#assert_in_delta | Passes if |
#assert_in_epsilon | Passes if |
#assert_include | Passes if |
#assert_includes | Alias for Assertions#assert_include. |
#assert_instance_of | Passes if |
#assert_kind_of | Passes if |
#assert_match | Passes if |
#assert_nil | Passes if |
#assert_no_match | Deprecated. |
#assert_not_const_defined | Passes if ! |
#assert_not_empty | Passes if |
#assert_not_equal | Passes if |
#assert_not_in_delta | Passes if |
#assert_not_in_epsilon | Passes if |
#assert_not_include | Passes if |
#assert_not_includes | Alias for Assertions#assert_not_include. |
#assert_not_instance_of | Passes if |
#assert_not_kind_of | Passes if |
#assert_not_match | Passes if |
#assert_not_nil | Passes if ! |
#assert_not_operator | Compares the |
#assert_not_predicate | Passes if |
#assert_not_respond_to | Passes if |
#assert_not_same | Passes if ! |
#assert_not_send | Passes if the method send doesn't return a true value. |
#assert_nothing_raised | Passes if block does not raise an exception. |
#assert_nothing_thrown | Passes if block does not throw anything. |
#assert_operator | Compares the |
#assert_path_exist | Passes if |
#assert_path_not_exist | Passes if |
#assert_predicate | Passes if |
#assert_raise | Passes if the block raises one of the expected exceptions. |
#assert_raise_kind_of | Passes if the block raises one of the given exceptions or sub exceptions of the given exceptions. |
#assert_raise_message | Passes if an exception is raised in block and its message is |
#assert_raises | Alias for Assertions#assert_raise. |
#assert_respond_to | Passes if |
#assert_same | Passes if |
#assert_send | Passes if the method send returns a true value. |
#assert_throw | Passes if the block throws |
#assert_throws | Alias for Assertions#assert_throw. |
#assert_true | Passes if |
#build_message | Builds a failure message. |
#flunk | Flunk always fails. |
#refute | Asserts that |
#refute_empty | Alias for Assertions#assert_not_empty. |
#refute_equal | Alias for Assertions#assert_not_equal. |
#refute_in_delta | Alias for Assertions#assert_not_in_delta. |
#refute_in_epsilon | Alias for Assertions#assert_not_in_epsilon. |
#refute_includes | Alias for Assertions#assert_not_include. |
#refute_instance_of | Alias for Assertions#assert_not_instance_of. |
#refute_kind_of | Alias for Assertions#assert_not_kind_of. |
#refute_match | Alias for Assertions#assert_not_match. |
#refute_nil | Alias for Assertions#assert_not_nil. |
#refute_operator | Alias for Assertions#assert_not_operator. |
#refute_predicate | Alias for Assertions#assert_not_predicate. |
#refute_respond_to | Alias for Assertions#assert_not_respond_to. |
#refute_same | Alias for Assertions#assert_not_same. |
#_assert_in_delta_message, #_assert_in_delta_validate_arguments, #_assert_in_epsilon_message, #_assert_in_epsilon_validate_arguments, #_assert_raise, #_set_failed_information, #_wrap_assertion |
Priority - Included
TestCaseNotificationSupport - Included
#notify | Notify some information. |
#add_notification |
TestCaseOmissionSupport - Included
#omit | Omit the test or part of the test. |
#omit_if | Omit the test or part of the test if condition is true. |
#omit_unless | Omit the test or part of the test if condition is not true. |
#add_omission |
TestCasePendingSupport - Included
#pend | Marks the test or part of the test is pending. |
#add_pending |
FailureHandler - Included
#add_failure | Report a failure. |
#handle_assertion_failed_error |
ErrorHandler - Included
Fixture - Included
#create_fixtures_runner, #run_cleanup, #run_fixture, #run_fixture_callback, #run_setup, #run_teardown |
Attribute - Included
Constructor Details
.new(test_method_name) ⇒ TestCase
Creates a new instance of the fixture for running the test represented by test_method_name.
# File 'lib/test/unit/testcase.rb', line 461
def initialize(test_method_name) @method_name = test_method_name @internal_data = InternalData.new end
Class Attribute Details
.test_order (rw)
Returns the current test order. This returns :alphabetic
by default.
# File 'lib/test/unit/testcase.rb', line 251
def test_order ancestors.each do |ancestor| order = @@test_orders[ancestor] return order if order end AVAILABLE_ORDERS.first end
.test_order=(order) (rw)
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 268
def test_order=(order) @@test_orders[self] = order end
Class Method Details
.added_method_names
# File 'lib/test/unit/testcase.rb', line 162
def added_method_names # :nodoc: (@@added_method_names[self] ||= {}).keys end
.description(value, target = nil)
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 331
def description(value, target=nil) targets = [target].compact attribute(:description, value, {}, *targets) end
.find_locations(query)
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 397
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
.inherited(sub_class)
# File 'lib/test/unit/testcase.rb', line 128
def inherited(sub_class) # :nodoc: DESCENDANTS << sub_class super end
.method_added(name)
# File 'lib/test/unit/testcase.rb', line 134
def method_added(name) # :nodoc: super added_method_names = (@@added_method_names[self] ||= {}) stringified_name = name.to_s if added_method_names.key?(stringified_name) attribute(:redefined, {:backtrace => caller}, {}, stringified_name) end source_location = find_attribute(stringified_name, :source_location) if source_location path, line = source_location elsif respond_to?(:caller_locations, true) location = caller_locations(1, 1)[0] path = location.absolute_path || location.path line = location.lineno else # TODO: Remove me when Ruby 1.9 support is dropped path, line, = caller[0].split(/:(\d+)/, 2) line = line.to_i if line end method_locations << { :method_name => stringified_name, :path => File. (path), :line => line, } added_method_names[stringified_name] = true AutoRunnerLoader.check(self, stringified_name) end
.method_locations (private)
# File 'lib/test/unit/testcase.rb', line 430
def method_locations @@method_locations[self] ||= [] end
.shutdown
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 244
def shutdown end
.startup
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 208
def startup end
.sub_test_case(name) { ... } ⇒ TestCase
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”.
# File 'lib/test/unit/testcase.rb', line 371
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
.suite
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 169
def suite suite_creator = TestSuiteCreator.new(self) suite_creator.create end
.target_method_locations(path) (private)
# File 'lib/test/unit/testcase.rb', line 435
def target_method_locations(path) 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. (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
.test(*test_description_or_targets, &block)
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 294
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 = "wrong number of arguments (#{n_arguments} for 1)" raise ArgumentError, 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
.test_defined?(query) ⇒ Boolean
Checks whether a test that is matched the query is defined.
# File 'lib/test/unit/testcase.rb', line 392
def test_defined?(query) locations = find_locations(query) not locations.empty? end
Instance Attribute Details
#interrupted? ⇒ Boolean
(readonly)
Returns whether the test is interrupted.
# File 'lib/test/unit/testcase.rb', line 733
def interrupted? @internal_data.interrupted? end
#method_name (readonly)
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 457
attr_reader :method_name
#passed? ⇒ Boolean
(readonly)
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 740
def passed? @internal_data.passed? end
#valid? ⇒ Boolean
(readonly)
Returns the test is valid test. It is used in internal.
# File 'lib/test/unit/testcase.rb', line 472
def valid? # :nodoc: return false unless respond_to?(@method_name) test_method = method(@method_name) unless @internal_data.have_test_data? return false unless test_method.arity <= 0 end owner = Util::MethodOwnerFinder.find(self, @method_name) if owner.class != Module and self.class != owner return false end true end
Instance Method Details
#==(other)
It's handy to be able to compare TestCase
instances.
# File 'lib/test/unit/testcase.rb', line 715
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
#add_assertion (private)
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 809
def add_assertion current_result.add_assertion end
#add_pass ⇒ void
This method returns an undefined value.
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.
# File 'lib/test/unit/testcase.rb', line 764
def add_pass current_result.add_pass end
#assign_test_data(label, data)
Assigns test data to the test. It is used in internal.
# File 'lib/test/unit/testcase.rb', line 467
def assign_test_data(label, data) # :nodoc: @internal_data.assign_test_data(label, data) end
#cleanup
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 620
def cleanup end
#current_result (private)
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 769
def current_result @_result end
#data_label
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 677
def data_label @internal_data.test_data_label end
#default_test
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 666
def default_test flunk("No tests were specified") end
#description
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 705
def description self[:description] || name end
#elapsed_time
Returns elapsed time for the test was ran.
# File 'lib/test/unit/testcase.rb', line 728
def elapsed_time @internal_data.elapsed_time end
#handle_exception(exception) (private)
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 797
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
#local_name
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 692
def local_name if @internal_data.have_test_data? "#{@method_name}[#{data_label}]" else @method_name.to_s end end
#name
Returns a human-readable name for the specific test that this instance of TestCase
represents.
# File 'lib/test/unit/testcase.rb', line 683
def name "#{local_name}(#{self.class.name})" end
#problem_occurred ⇒ void
This method returns an undefined value.
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.
# File 'lib/test/unit/testcase.rb', line 751
def problem_occurred @internal_data.problem_occurred end
#run(result)
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 488
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
#run_test (private)
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 773
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) if test_method.arity == 1 or test_method.arity < 0 __send__(@method_name, @internal_data.test_data) else locations = self.class.find_locations(:method_name => @method_name) backtrace = locations.collect do |location| "#{location[:path]}:#{location[:line]}" end notify("<#{signature}> misses a parameter to take test data", :backtrace => backtrace) end else __send__(@method_name) end end
#setup
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 575
def setup end
#size
[ GitHub ]# File 'lib/test/unit/testcase.rb', line 670
def size 1 end
#start_time
Returns a Time at the test was started.
# File 'lib/test/unit/testcase.rb', line 723
def start_time @internal_data.start_time end
#teardown
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 663
def teardown end
#to_s
Overridden to return #name.
# File 'lib/test/unit/testcase.rb', line 710
def to_s name end