diff options
author | ntalbott <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-10-08 13:21:28 +0000 |
---|---|---|
committer | ntalbott <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-10-08 13:21:28 +0000 |
commit | 09d2946061379d18407d4de2002a01f3a82c8c84 (patch) | |
tree | eaefbd65eb42404ac9230f108bed0576943269ca /lib/test | |
parent | 777681bda1fe3fbc33bd2c3d4ce132e6b8c0042e (diff) |
* lib/test/unit.rb: removed installation instructions.
* lib/test/unit/ui/testrunnermediator.rb: moved the run flag to a more
central location.
* lib/test/unit.rb: ditto.
* lib/test/unit.rb: extracted the running code in to AutoRunner.
* lib/test/unit/autorunner.rb: added.
* lib/test/unit/collector/objectspace.rb: extracted common test
collection functionality in to a module.
* lib/test/unit/collector.rb: ditto; added.
* test/testunit/collector/test_objectspace.rb: ditto.
* lib/test/unit/collector/dir.rb: added. Supports collecting tests out
of a directory structure.
* test/testunit/collector/test_dir.rb: added.
* test/runner.rb: simplified to use the new capabilities.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4720 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/test')
-rw-r--r-- | lib/test/unit.rb | 130 | ||||
-rw-r--r-- | lib/test/unit/autorunner.rb | 178 | ||||
-rw-r--r-- | lib/test/unit/collector.rb | 43 | ||||
-rw-r--r-- | lib/test/unit/collector/dir.rb | 80 | ||||
-rw-r--r-- | lib/test/unit/collector/objectspace.rb | 30 | ||||
-rw-r--r-- | lib/test/unit/ui/testrunnermediator.rb | 10 |
6 files changed, 319 insertions, 152 deletions
diff --git a/lib/test/unit.rb b/lib/test/unit.rb index 08e57f2f17..6fab874f23 100644 --- a/lib/test/unit.rb +++ b/lib/test/unit.rb @@ -19,20 +19,6 @@ # have tests for it. # # -# == Installation -# -# Run: -# * ruby setup.rb config -# * ruby setup.rb setup -# * ruby setup.rb install -# -# Note that the runit compatibility layer will *not* be installed if you -# already have RubyUnit installed. -# -# Mac OS X users should also note that setup.rb will fail unless they -# execute 'unlimit stacksize' before running it. -# -# # == Notes # # Test::Unit has grown out of and superceded Lapidary. @@ -272,114 +258,18 @@ require 'test/unit/testcase' -require 'test/unit/ui/testrunnermediator' -require 'test/unit/collector/objectspace' - -at_exit { - require 'optparse' - if (!Test::Unit::UI::TestRunnerMediator.run?) - output_level = nil - runners = { - :console => proc do |suite| - require 'test/unit/ui/console/testrunner' - output_level ||= Test::Unit::UI::Console::TestRunner::NORMAL - passed = Test::Unit::UI::Console::TestRunner.run(suite, output_level).passed? - exit(passed ? 0 : 1) - end, - :gtk => proc do |suite| - require 'test/unit/ui/gtk/testrunner' - Test::Unit::UI::GTK::TestRunner.run(suite) - end, - :fox => proc do |suite| - require 'test/unit/ui/fox/testrunner' - Test::Unit::UI::Fox::TestRunner.run(suite) - end, - } - - runner = runners[:console] - filters = [] - catch(:stop_processing) do - ARGV.options do |o| - o.program_name = "test/unit.rb" - o.banner = "Test::Unit automatic runner." - o.banner = "#{$0} [options] [-- untouched arguments]" +require 'test/unit/autorunner' - o.on - runner_display = runners.keys.collect{|r| r.to_s.sub(/^(.)/, '[\\1]')}.join(", ") - o.on('-r', '--runner=RUNNER', runners.keys, - "Use the given runner.", - "(" + runner_display + ")"){|r| runner = runners[r]} - o.on('-n', '--name=NAME', String, - "Runs tests matching NAME", - "(patterns may be used).") do |n| - n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) - case n - when Regexp - filters << proc{|t| n =~ t.method_name} - else - filters << proc{|t| n == t.method_name} - end - end - o.on('-t', '--testcase=TESTCASE', String, - "Runs tests in TestCases matching TESTCASE", - "(patterns may be used).") do |n| - n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) - case n - when Regexp - filters << proc{|t| n =~ t.class.name} - else - filters << proc{|t| n == t.class.name} - end - end - o.on('-v', '--verbose=[LEVEL]', (0..3).to_a.collect{|i| i.to_s}, - "Set output level.", - "Levels are:", - " 0 = SILENT", - " 1 = PROGRESS_ONLY", - " 2 = NORMAL", - " 3 = VERBOSE (default)", - " Only valid for the console runner."){|l| output_level = (l ? l.to_i : 3)} - o.on('--', - "Stop processing options so that", - "remaining options will be passed", - "to the test."){throw :stop_processing} - o.on('-h', '--help', 'Display this help.'){puts o; exit(0)} - - o.on_tail - o.on_tail('Deprecated options:') - o.on_tail('--console', 'Console runner (use --runner).') do - warn("Deprecated option (--console).") - runner = runners[:console] - end - o.on_tail('--gtk', 'GTK runner (use --runner).') do - warn("Deprecated option (--gtk).") - runner = runners[:gtk] - end - o.on_tail('--fox', 'Fox runner (use --runner).') do - warn("Deprecated option (--fox).") - runner = runners[:fox] - end - o.on_tail - - begin - o.parse! - rescue OptionParser::ParseError => e - puts e - puts o - exit(1) - end - end +module Test + module Unit + def self.run=(flag) + @run = flag end - if(output_level && !(runner == runners[:console])) - puts "Invalid arguments: You can only specify an output level with the console runner." - exit(1) + def self.run? + @run ||= false end - - collector = Test::Unit::Collector::ObjectSpace::new - collector.filter = filters - - suite_name = $0.sub(/\.rb$/, '') - runner.call(collector.collect(suite_name)) end -} +end + +at_exit{Test::Unit::AutoRunner.run($0) unless(Test::Unit.run?)} diff --git a/lib/test/unit/autorunner.rb b/lib/test/unit/autorunner.rb new file mode 100644 index 0000000000..be32e47f6e --- /dev/null +++ b/lib/test/unit/autorunner.rb @@ -0,0 +1,178 @@ +require 'optparse' + +require 'test/unit/ui/console/testrunner' + +module Test + module Unit + class AutoRunner + def self.run(current_file=nil, default_dir=nil, &block) + if(!current_file || current_file == $0) + r = new(!current_file, &block) + if(default_dir && r.to_run.empty?) + r.to_run = default_dir + end + r.run + end + end + + RUNNERS = { + :console => proc do |r| + output_level = r.output_level || Test::Unit::UI::Console::TestRunner::NORMAL + passed = Test::Unit::UI::Console::TestRunner.run(r.suite, output_level).passed? + exit(passed ? 0 : 1) + end, + :gtk => proc do |r| + require 'test/unit/ui/gtk/testrunner' + Test::Unit::UI::GTK::TestRunner.run(r.suite) + end, + :fox => proc do |suite| + require 'test/unit/ui/fox/testrunner' + Test::Unit::UI::Fox::TestRunner.run(r.suite) + end, + } + + OUTPUT_LEVELS = { + :silent => UI::Console::TestRunner::SILENT, + :progress => UI::Console::TestRunner::PROGRESS_ONLY, + :normal => UI::Console::TestRunner::NORMAL, + :verbose => UI::Console::TestRunner::VERBOSE, + } + + COLLECTORS = { + :objectspace => proc do |r| + require 'test/unit/collector/objectspace' + c = Collector::ObjectSpace.new + c.filter = r.filters + c.collect($0.sub(/\.rb\Z/, '')) + end, + :dir => proc do |r| + require 'test/unit/collector/dir' + c = Collector::Dir.new + c.filter = r.filters + c.pattern = r.pattern if(r.pattern) + c.collect(*(r.to_run.empty? ? ['.'] : r.to_run)) + end, + } + + attr_reader :suite + attr_accessor :output_level, :filters, :to_run, :pattern + attr_writer :runner, :collector + + def initialize(standalone) + Unit.run = true + @standalone = standalone + @runner = RUNNERS[:console] + @collector = COLLECTORS[(standalone ? :dir : :objectspace)] + @filters = [] + @to_run = [] + process_args + yield(self) if(block_given?) + end + + def process_args + catch(:stop_processing) do + ARGV.options do |o| + o.program_name = "test/unit.rb" + o.banner = "Test::Unit automatic runner." + o.banner = "#{$0} [options] [-- untouched arguments]" + + o.on + o.on('-r', '--runner=RUNNER', RUNNERS.keys, + "Use the given RUNNER.", + "(" + keyword_display(RUNNERS.keys) + ")") do |r| + @runner = runners[r] + end + + if(@standalone) + o.on('-a', '--add=TORUN', Array, + "Add TORUN to the list of things to run;", + "can be a file or a directory.") do |a| + @to_run.concat(a) + end + + o.on('-p', '--pattern=PATTERN', String, + "Match files to collect against PATTERN.") do |e| + @pattern = Regexp.new(e.sub(%r{\A/(.*)/\Z}m, '\\1')) + end + end + + o.on('-n', '--name=NAME', String, + "Runs tests matching NAME.", + "(patterns may be used).") do |n| + n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) + case n + when Regexp + @filters << proc{|t| n =~ t.method_name ? true : nil} + else + @filters << proc{|t| n == t.method_name ? true : nil} + end + end + + o.on('-t', '--testcase=TESTCASE', String, + "Runs tests in TestCases matching TESTCASE.", + "(patterns may be used).") do |n| + n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n) + case n + when Regexp + @filters << proc{|t| n =~ t.class.name ? true : nil} + else + @filters << proc{|t| n == t.class.name ? true : nil} + end + end + + o.on('-v', '--verbose=[LEVEL]', OUTPUT_LEVELS.keys, + "Set the output level (default is verbose).", + "(" + keyword_display(OUTPUT_LEVELS.keys) + ")") do |l| + @output_level = (l ? OUTPUT_LEVELS[l] : OUTPUT_LEVELS[:verbose]) + end + + o.on('--', + "Stop processing options so that the", + "remaining options will be passed to the", + "test."){throw :stop_processing} + + o.on('-h', '--help', 'Display this help.'){puts o; exit(0)} + + o.on_tail + o.on_tail('Deprecated options:') + + o.on_tail('--console', 'Console runner (use --runner).') do + warn("Deprecated option (--console).") + @runner = RUNNERS[:console] + end + + o.on_tail('--gtk', 'GTK runner (use --runner).') do + warn("Deprecated option (--gtk).") + @runner = RUNNERS[:gtk] + end + + o.on_tail('--fox', 'Fox runner (use --runner).') do + warn("Deprecated option (--fox).") + @runner = RUNNERS[:fox] + end + + o.on_tail + + begin + o.parse! + rescue OptionParser::ParseError => e + puts e + puts o + exit(1) + end + end + end + @filters << proc{false} unless(@filters.empty?) + end + + def keyword_display(array) + array.collect{|e| e.to_s.sub(/^(.)(.+)$/, '\\1[\\2]')}.join(", ") + end + + def run + @suite = @collector[self] + @runner[self] + end + end + end +end diff --git a/lib/test/unit/collector.rb b/lib/test/unit/collector.rb new file mode 100644 index 0000000000..9e9e654147 --- /dev/null +++ b/lib/test/unit/collector.rb @@ -0,0 +1,43 @@ +module Test + module Unit + module Collector + def initialize + @filters = [] + end + + def filter=(filters) + @filters = case(filters) + when Proc + [filters] + when Array + filters + end + end + + def add_suite(destination, suite) + to_delete = suite.tests.find_all{|t| !include?(t)} + to_delete.each{|t| suite.delete(t)} + destination << suite unless(suite.size == 0) + end + + def include?(test) + return true if(@filters.empty?) + @filters.each do |filter| + result = filter[test] + if(result.nil?) + next + elsif(!result) + return false + else + return true + end + end + true + end + + def sort(suites) + suites.sort_by{|s| s.name} + end + end + end +end diff --git a/lib/test/unit/collector/dir.rb b/lib/test/unit/collector/dir.rb new file mode 100644 index 0000000000..b5c935519e --- /dev/null +++ b/lib/test/unit/collector/dir.rb @@ -0,0 +1,80 @@ +require 'test/unit/testsuite' +require 'test/unit/collector' + +module Test + module Unit + module Collector + class Dir + include Collector + + attr_writer :pattern + + def initialize(dir=::Dir, file=::File, object_space=::ObjectSpace, req=nil) + super() + @dir = dir + @file = file + @object_space = object_space + @req = req + @pattern = /\Atest_.*\.rb\Z/m + end + + def collect(*from) + if(from.empty?) + recursive_collect('.', find_test_cases) + elsif(from.size == 1) + recursive_collect(from.first, find_test_cases) + else + suites = [] + from.each do |f| + suite = recursive_collect(f, find_test_cases) + suites << suite unless(suite.tests.empty?) + end + suite = TestSuite.new("[#{from.join(', ')}]") + sort(suites).each{|s| suite << s} + suite + end + end + + def find_test_cases(ignore=[]) + cases = [] + @object_space.each_object(Class) do |c| + cases << c if(c < TestCase && !ignore.include?(c)) + end + ignore.concat(cases) + cases + end + + def recursive_collect(name, already_gathered) + sub_suites = [] + if(@file.directory?(name)) + @dir.entries(name).each do |e| + next if(e == '.' || e == '..') + e_name = @file.join(name, e) + if(@file.directory?(e_name)) + sub_suite = recursive_collect(e_name, already_gathered) + sub_suites << sub_suite unless(sub_suite.empty?) + else + (next unless(@pattern =~ e)) if(@pattern) + collect_file(e_name, sub_suites, already_gathered) + end + end + else + collect_file(name, sub_suites, already_gathered) + end + suite = TestSuite.new(@file.basename(name)) + sort(sub_suites).each{|s| suite << s} + suite + end + + def collect_file(name, suites, already_gathered) + if(@req) + @req.require(name) + else + require(name) + end + find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)} + end + end + end + end +end diff --git a/lib/test/unit/collector/objectspace.rb b/lib/test/unit/collector/objectspace.rb index 5a1d29cc1a..d1127a981f 100644 --- a/lib/test/unit/collector/objectspace.rb +++ b/lib/test/unit/collector/objectspace.rb @@ -2,15 +2,19 @@ # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # License:: Ruby license. +require 'test/unit/collector' + module Test module Unit module Collector class ObjectSpace + include Collector + NAME = 'collected from the ObjectSpace' def initialize(source=::ObjectSpace) + super() @source = source - @filters = [] end def collect(name=NAME) @@ -18,32 +22,12 @@ module Test sub_suites = [] @source.each_object(Class) do |klass| if(Test::Unit::TestCase > klass) - sub_suite = klass.suite - to_delete = sub_suite.tests.find_all{|t| !include(t)} - to_delete.each{|t| sub_suite.delete(t)} - sub_suites << sub_suite unless(sub_suite.size == 0) + add_suite(sub_suites, klass.suite) end end - sub_suites.sort_by{|s| s.name}.each{|s| suite << s} + sort(sub_suites).each{|s| suite << s} suite end - - def include(test) - return true if(@filters.empty?) - @filters.each do |filter| - return true if(filter.call(test)) - end - false - end - - def filter=(filters) - @filters = case(filters) - when Proc - [filters] - when Array - filters - end - end end end end diff --git a/lib/test/unit/ui/testrunnermediator.rb b/lib/test/unit/ui/testrunnermediator.rb index 41c77dc7a9..bd051e2a51 100644 --- a/lib/test/unit/ui/testrunnermediator.rb +++ b/lib/test/unit/ui/testrunnermediator.rb @@ -20,14 +20,6 @@ module Test include Util::Observable - @@run = false - - # Returns true if any TestRunnerMediator instances - # have been run. - def self.run? - return @@run - end - # Creates a new TestRunnerMediator initialized to run # the passed suite. def initialize(suite) @@ -37,7 +29,7 @@ module Test # Runs the suite the TestRunnerMediator was created # with. def run_suite - @@run = true + Unit.run = true begin_time = Time.now notify_listeners(RESET, @suite.size) result = create_result |