summaryrefslogtreecommitdiff
path: root/lib/test
diff options
context:
space:
mode:
authorntalbott <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-10-08 13:21:28 +0000
committerntalbott <ntalbott@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-10-08 13:21:28 +0000
commit09d2946061379d18407d4de2002a01f3a82c8c84 (patch)
treeeaefbd65eb42404ac9230f108bed0576943269ca /lib/test
parent777681bda1fe3fbc33bd2c3d4ce132e6b8c0042e (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.rb130
-rw-r--r--lib/test/unit/autorunner.rb178
-rw-r--r--lib/test/unit/collector.rb43
-rw-r--r--lib/test/unit/collector/dir.rb80
-rw-r--r--lib/test/unit/collector/objectspace.rb30
-rw-r--r--lib/test/unit/ui/testrunnermediator.rb10
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