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
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 349
def description(value, target=nil)
targets = [target].compact
attribute(:description, value, {}, *targets)
end
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 441
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 528
def initialize(test_method_name)
@method_name = test_method_name
@internal_data = InternalData.new
end
Declares that the following test uses Ractor.
Tests that use Ractor are executed at the end. Because multi Ractor mode is enabled in the current process and it's not disabled even when only one Ractor is running after running a test that uses Ractor on Ruby 3.0. It will be solved in Ruby 3.1.
This is implemented by setting the `:ractor` attribute of the test to `true`.
@param options [Hash] See {Attribute::ClassMethods#attribute}
for details.
@return [void]
@example Declares that test_do_something_with_ractor uses Ractor
ractor def test_do_something_with_ractor Ractor.new do # ... end end
@since 3.4.6
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 380
def ractor(options={})
attribute(:ractor, true, options)
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 259
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 221
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 421
def sub_test_case(name, &block)
sub_test_case = sub_test_case_class(name)
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 180
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 312
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 436
def test_defined?(query)
locations = find_locations(query)
not locations.empty?
end
Returns the current test order. This returns `:alphabetic` by default.
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 266
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 286
def test_order=(order)
@@test_orders[self] = order
end
It's handy to be able to compare TestCase instances.
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 794
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 843
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 691
def cleanup
end
Returns test data for the test. If the test isn't associated with any test data, it returns `nil`.
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 756
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 750
def data_label
@internal_data.test_data_label
end
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 739
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 784
def description
self[:description] || name
end
Returns elapsed time for the test was ran.
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 807
def elapsed_time
@internal_data.elapsed_time
end
Returns whether the test is interrupted.
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 812
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 771
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 762
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 819
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 830
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 555
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 644
def setup
end
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 743
def size
1
end
Returns a Time at the test was started.
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 802
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 test-unit-3.5.3/lib/test/unit/testcase.rb, line 736
def teardown
end
Overridden to return name.
# File test-unit-3.5.3/lib/test/unit/testcase.rb, line 789
def to_s
name
end