[cairo-commit] rcairo/test-unit/lib/test/unit assertionfailederror.rb, NONE, 1.1 assertions.rb, NONE, 1.1 attribute.rb, NONE, 1.1 autorunner.rb, NONE, 1.1 collector.rb, NONE, 1.1 color.rb, NONE, 1.1 diff.rb, NONE, 1.1 error.rb, NONE, 1.1 exceptionhandler.rb, NONE, 1.1 failure.rb, NONE, 1.1 fixture.rb, NONE, 1.1 notification.rb, NONE, 1.1 omission.rb, NONE, 1.1 pending.rb, NONE, 1.1 priority.rb, NONE, 1.1 testcase.rb, NONE, 1.1 testresult.rb, NONE, 1.1 testsuite.rb, NONE, 1.1 version.rb, NONE, 1.1
Kouhei Sutou
commit at pdx.freedesktop.org
Wed Aug 13 01:20:56 PDT 2008
- Previous message: [cairo-commit] rcairo/test-unit/lib/test unit.rb,NONE,1.1
- Next message: [cairo-commit] rcairo/test-unit/lib/test/unit/collector descendant.rb, NONE, 1.1 dir.rb, NONE, 1.1 load.rb, NONE, 1.1 objectspace.rb, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: kou
Update of /cvs/cairo/rcairo/test-unit/lib/test/unit
In directory kemper:/tmp/cvs-serv10309/test-unit/lib/test/unit
Added Files:
assertionfailederror.rb assertions.rb attribute.rb
autorunner.rb collector.rb color.rb diff.rb error.rb
exceptionhandler.rb failure.rb fixture.rb notification.rb
omission.rb pending.rb priority.rb testcase.rb testresult.rb
testsuite.rb version.rb
Log Message:
* test-unit: imported Test::Unit 2.x.
--- NEW FILE: assertionfailederror.rb ---
#--
#
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
module Test
module Unit
# Thrown by Test::Unit::Assertions when an assertion fails.
class AssertionFailedError < StandardError
end
end
end
--- NEW FILE: assertions.rb ---
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
require 'test/unit/assertionfailederror'
require 'test/unit/util/backtracefilter'
require 'test/unit/diff'
module Test
module Unit
##
# Test::Unit::Assertions contains the standard Test::Unit assertions.
# Assertions is included in Test::Unit::TestCase.
#
# To include it in your own code and use its functionality, you simply
# need to rescue Test::Unit::AssertionFailedError. Additionally you may
# override add_assertion to get notified whenever an assertion is made.
#
# Notes:
# * The message to each assertion, if given, will be propagated with the
# failure.
# * It is easy to add your own assertions based on assert_block().
#
# = Example Custom Assertion
#
# def deny(boolean, message = nil)
# message = build_message message, '<?> is not false or nil.', boolean
# assert_block message do
# not boolean
# end
# end
module Assertions
##
# The assertion upon which all other assertions are based. Passes if the
# block yields true.
#
# Example:
# assert_block "Couldn't do the thing" do
# do_the_thing
# end
public
def assert_block(message="assert_block failed.") # :yields:
_wrap_assertion do
if (! yield)
raise AssertionFailedError.new(message.to_s)
end
end
end
##
# Asserts that +boolean+ is not false or nil.
#
# Example:
# assert [1, 2].include?(5)
public
def assert(boolean, message=nil)
_wrap_assertion do
assert_block("assert should not be called with a block.") { !block_given? }
assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
end
end
##
# Passes if +expected+ == +actual.
#
# Note that the ordering of arguments is important, since a helpful
# error message is generated when this one fails that tells you the
# values of expected and actual.
#
# Example:
# assert_equal 'MY STRING', 'my string'.upcase
public
def assert_equal(expected, actual, message=nil)
diff = AssertionMessage.delayed_literal do
if !expected.is_a?(String) or !actual.is_a?(String)
expected = AssertionMessage.convert(expected)
actual = AssertionMessage.convert(actual)
end
diff = Diff.readable(expected, actual)
if /^[-+]/ !~ diff
diff = ""
elsif /^[ ?]/ =~ diff or /(?:.*\n){2,}/ =~ diff
diff = "\n\ndiff:\n#{diff}"
else
diff = ""
end
diff
end
full_message = build_message(message, <<EOT, expected, actual, diff)
<?> expected but was
<?>.?
EOT
assert_block(full_message) { expected == actual }
end
private
def _check_exception_class(args) # :nodoc:
args.partition do |klass|
next if klass.instance_of?(Module)
assert(Exception >= klass, "Should expect a class of exception, #{klass}")
true
end
end
private
def _expected_exception?(actual_exception, exceptions, modules) # :nodoc:
exceptions.include?(actual_exception.class) or
modules.any? {|mod| actual_exception.is_a?(mod)}
end
##
# Passes if the block raises one of the given exceptions.
#
# Example:
# assert_raise RuntimeError, LoadError do
# raise 'Boom!!!'
# end
public
def assert_raise(*args)
_wrap_assertion do
if Module === args.last
message = ""
else
message = args.pop
end
exceptions, modules = _check_exception_class(args)
expected = args.size == 1 ? args.first : args
actual_exception = nil
full_message = build_message(message, "<?> exception expected but none was thrown.", expected)
assert_block(full_message) do
begin
yield
rescue Exception => actual_exception
break
end
false
end
full_message = build_message(message, "<?> exception expected but was\n?", expected, actual_exception)
assert_block(full_message) {_expected_exception?(actual_exception, exceptions, modules)}
actual_exception
end
end
##
# Alias of assert_raise.
#
# Will be deprecated in 1.9, and removed in 2.0.
public
def assert_raises(*args, &block)
assert_raise(*args, &block)
end
##
# Passes if +object+ .instance_of? +klass+
#
# Example:
# assert_instance_of String, 'foo'
public
def assert_instance_of(klass, object, message="")
_wrap_assertion do
assert_equal(Class, klass.class, "assert_instance_of takes a Class as its first argument")
full_message = build_message(message, <<EOT, object, klass, object.class)
<?> expected to be an instance of
<?> but was
<?>.
EOT
assert_block(full_message){object.instance_of?(klass)}
end
end
##
# Passes if +object+ is nil.
#
# Example:
# assert_nil [1, 2].uniq!
public
def assert_nil(object, message="")
full_message = build_message(message, <<EOT, object)
<?> expected to be nil.
EOT
assert_block(full_message) { object.nil? }
end
##
# Passes if +object+ .kind_of? +klass+
#
# Example:
# assert_kind_of Object, 'foo'
public
def assert_kind_of(klass, object, message="")
_wrap_assertion do
assert(klass.kind_of?(Module), "The first parameter to assert_kind_of should be a kind_of Module.")
full_message = build_message(message, "<?>\nexpected to be kind_of\\?\n<?> but was\n<?>.", object, klass, object.class)
assert_block(full_message){object.kind_of?(klass)}
end
end
##
# Passes if +object+ .respond_to? +method+
#
# Example:
# assert_respond_to 'bugbear', :slice
public
def assert_respond_to(object, method, message="")
_wrap_assertion do
full_message = build_message(nil, "<?>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to\\?(:to_str).", method)
assert_block(full_message) do
method.kind_of?(Symbol) || method.respond_to?(:to_str)
end
full_message = build_message(message, <<EOT, object, object.class, method)
<?>
of type <?>
expected to respond_to\\?<?>.
EOT
assert_block(full_message) { object.respond_to?(method) }
end
end
##
# Passes if +string+ =~ +pattern+.
#
# Example:
# assert_match(/\d+/, 'five, 6, seven')
public
def assert_match(pattern, string, message="")
_wrap_assertion do
pattern = case(pattern)
when String
Regexp.new(Regexp.escape(pattern))
else
pattern
end
full_message = build_message(message, "<?> expected to be =~\n<?>.", string, pattern)
assert_block(full_message) { string =~ pattern }
end
end
##
# Passes if +actual+ .equal? +expected+ (i.e. they are the same
# instance).
#
# Example:
# o = Object.new
# assert_same o, o
public
def assert_same(expected, actual, message="")
full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
<?>
with id <?> expected to be equal\\? to
<?>
with id <?>.
EOT
assert_block(full_message) { actual.equal?(expected) }
end
##
# Compares the +object1+ with +object2+ using +operator+.
#
# Passes if object1.__send__(operator, object2) is true.
#
# Example:
# assert_operator 5, :>=, 4
public
def assert_operator(object1, operator, object2, message="")
_wrap_assertion do
full_message = build_message(nil, "<?>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to\\?(:to_str).", operator)
assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)}
full_message = build_message(message, <<EOT, object1, AssertionMessage.literal(operator), object2)
<?> expected to be
?
<?>.
EOT
assert_block(full_message) { object1.__send__(operator, object2) }
end
end
##
# Passes if block does not raise an exception.
#
# Example:
# assert_nothing_raised do
# [1, 2].uniq
# end
public
def assert_nothing_raised(*args)
_wrap_assertion do
if Module === args.last
message = ""
else
message = args.pop
end
exceptions, modules = _check_exception_class(args)
begin
yield
rescue Exception => e
if ((args.empty? && !e.instance_of?(AssertionFailedError)) ||
_expected_exception?(e, exceptions, modules))
assert_block(build_message(message, "Exception raised:\n?", e)){false}
else
raise
end
end
nil
end
end
##
# Flunk always fails.
#
# Example:
# flunk 'Not done testing yet.'
public
def flunk(message="Flunked")
assert_block(build_message(message)){false}
end
##
# Passes if ! +actual+ .equal? +expected+
#
# Example:
# assert_not_same Object.new, Object.new
public
def assert_not_same(expected, actual, message="")
full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
<?>
with id <?> expected to not be equal\\? to
<?>
with id <?>.
EOT
assert_block(full_message) { !actual.equal?(expected) }
end
##
# Passes if +expected+ != +actual+
#
# Example:
# assert_not_equal 'some string', 5
public
def assert_not_equal(expected, actual, message="")
full_message = build_message(message, "<?> expected to be != to\n<?>.", expected, actual)
assert_block(full_message) { expected != actual }
end
##
# Passes if ! +object+ .nil?
#
# Example:
# assert_not_nil '1 two 3'.sub!(/two/, '2')
public
def assert_not_nil(object, message="")
full_message = build_message(message, "<?> expected to not be nil.", object)
assert_block(full_message){!object.nil?}
end
##
# Passes if +regexp+ !~ +string+
#
# Example:
# assert_no_match(/two/, 'one 2 three')
public
def assert_no_match(regexp, string, message="")
_wrap_assertion do
assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
full_message = build_message(message, "<?> expected to not match\n<?>.", regexp, string)
assert_block(full_message) { regexp !~ string }
end
end
UncaughtThrow = {
NameError => /^uncaught throw \`(.+)\'$/,
ArgumentError => /^uncaught throw (.+)$/,
ThreadError => /^uncaught throw \`(.+)\' in thread /
} #`
##
# Passes if the block throws +expected_object+
#
# Example:
# assert_throws :done do
# throw :done
# end
public
def assert_throws(expected_object, message="", &proc)
_wrap_assertion do
begin
catch([]) {}
rescue TypeError
assert_instance_of(Symbol, expected_object,
"assert_throws expects the symbol that should be thrown for its first argument")
end
assert_block("Should have passed a block to assert_throws.") do
block_given?
end
caught = true
begin
catch(expected_object) do
proc.call
caught = false
end
full_message = build_message(message,
"<?> should have been thrown.",
expected_object)
assert_block(full_message) {caught}
rescue NameError, ArgumentError, ThreadError => error
raise unless UncaughtThrow[error.class] =~ error.message
tag = $1
tag = tag[1..-1].intern if tag[0, 1] == ":"
full_message = build_message(message,
"<?> expected to be thrown but\n" +
"<?> was thrown.",
expected_object, tag)
flunk(full_message)
end
end
end
##
# Passes if block does not throw anything.
#
# Example:
# assert_nothing_thrown do
# [1, 2].uniq
# end
public
def assert_nothing_thrown(message="", &proc)
_wrap_assertion do
assert(block_given?, "Should have passed a block to assert_nothing_thrown")
begin
proc.call
rescue NameError, ArgumentError, ThreadError => error
raise unless UncaughtThrow[error.class] =~ error.message
tag = $1
tag = tag[1..-1].intern if tag[0, 1] == ":"
full_message = build_message(message,
"<?> was thrown when nothing was expected",
tag)
flunk(full_message)
end
assert(true, "Expected nothing to be thrown")
end
end
##
# Passes if +expected_float+ and +actual_float+ are equal
# within +delta+ tolerance.
#
# Example:
# assert_in_delta 0.05, (50000.0 / 10**6), 0.00001
public
def assert_in_delta(expected_float, actual_float, delta, message="")
_wrap_assertion do
{expected_float => "first float", actual_float => "second float", delta => "delta"}.each do |float, name|
assert_respond_to(float, :to_f, "The arguments must respond to to_f; the #{name} did not")
end
assert_operator(delta, :>=, 0.0, "The delta should not be negative")
full_message = build_message(message, <<EOT, expected_float, actual_float, delta)
<?> and
<?> expected to be within
<?> of each other.
EOT
assert_block(full_message) { (expected_float.to_f - actual_float.to_f).abs <= delta.to_f }
end
end
##
# Passes if the method send returns a true value.
#
# +send_array+ is composed of:
# * A receiver
# * A method
# * Arguments to the method
#
# Example:
# assert_send [[1, 2], :include?, 4]
public
def assert_send(send_array, message="")
_wrap_assertion do
assert_instance_of(Array, send_array, "assert_send requires an array of send information")
assert(send_array.size >= 2, "assert_send requires at least a receiver and a message name")
full_message = build_message(message, <<EOT, send_array[0], AssertionMessage.literal(send_array[1].to_s), send_array[2..-1])
<?> expected to respond to
<?(?)> with a true value.
EOT
assert_block(full_message) { send_array[0].__send__(send_array[1], *send_array[2..-1]) }
end
end
##
# Passes if +actual+ is a boolean value.
#
# Example:
# assert_boolean(true) # -> pass
# assert_boolean(nil) # -> fail
def assert_boolean(actual, message=nil)
_wrap_assertion do
assert_block(build_message(message,
"<true> or <false> expected but was\n<?>",
actual)) do
[true, false].include?(actual)
end
end
end
##
# Passes if +actual+ is true.
#
# Example:
# assert_true(true) # -> pass
# assert_true(:true) # -> fail
def assert_true(actual, message=nil)
_wrap_assertion do
assert_block(build_message(message,
"<true> expected but was\n<?>",
actual)) do
actual == true
end
end
end
##
# Passes if +actual+ is false.
#
# Example:
# assert_false(false) # -> pass
# assert_false(nil) # -> fail
def assert_false(actual, message=nil)
_wrap_assertion do
assert_block(build_message(message,
"<false> expected but was\n<?>",
actual)) do
actual == false
end
end
end
##
# Builds a failure message. +head+ is added before the +template+ and
# +arguments+ replaces the '?'s positionally in the template.
public
def build_message(head, template=nil, *arguments)
template &&= template.chomp
return AssertionMessage.new(head, template, arguments)
end
private
def _wrap_assertion
@_assertion_wrapped ||= false
unless (@_assertion_wrapped)
@_assertion_wrapped = true
begin
add_assertion
return yield
ensure
@_assertion_wrapped = false
end
else
return yield
end
end
##
# Called whenever an assertion is made. Define this in classes that
# include Test::Unit::Assertions to record assertion counts.
private
def add_assertion
end
##
# Select whether or not to use the pretty-printer. If this option is set
# to false before any assertions are made, pp.rb will not be required.
public
def self.use_pp=(value)
AssertionMessage.use_pp = value
end
# :stopdoc:
class AssertionMessage
@use_pp = true
class << self
attr_accessor :use_pp
def literal(value)
Literal.new(value)
end
def delayed_literal(&block)
DelayedLiteral.new(block)
end
def convert(object)
case object
when Exception
<<EOM.chop
Class: <#{convert(object.class)}>
Message: <#{convert(object.message)}>
---Backtrace---
#{Util::BacktraceFilter.filter_backtrace(object.backtrace).join("\n")}
---------------
EOM
else
if use_pp
begin
require 'pp' unless defined?(PP)
return PP.pp(object, '').chomp
rescue LoadError
self.use_pp = false
end
end
object.inspect
end
end
end
class Literal
def initialize(value)
@value = value
end
def inspect
@value.to_s
end
end
class DelayedLiteral
def initialize(value)
@value = value
end
def inspect
@value.call.to_s
end
end
class Template
def self.create(string)
parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : [])
self.new(parts)
end
attr_reader :count
def initialize(parts)
@parts = parts
@count = parts.find_all{|e| e == '?'}.size
end
def result(parameters)
raise "The number of parameters does not match the number of substitutions." if(parameters.size != count)
params = parameters.dup
@parts.collect{|e| e == '?' ? params.shift : e.gsub(/\\\?/m, '?')}.join('')
end
end
include Util::BacktraceFilter
def initialize(head, template_string, parameters)
@head = head
@template_string = template_string
@parameters = parameters
end
def convert(object)
self.class.convert(object)
end
def template
@template ||= Template.create(@template_string)
end
def add_period(string)
(string =~ /\.\Z/ ? string : string + '.')
end
def to_s
message_parts = []
if (@head)
head = @head.to_s
unless(head.empty?)
message_parts << add_period(head)
end
end
tail = template.result(@parameters.collect{|e| convert(e)})
message_parts << tail unless(tail.empty?)
message_parts.join("\n")
end
end
# :startdoc:
end
end
end
--- NEW FILE: attribute.rb ---
module Test
module Unit
module Attribute
class << self
def included(base)
base.extend(BaseClassMethods)
base.extend(ClassMethods)
end
end
module BaseClassMethods
def attributes_table
{}
end
end
module ClassMethods
def method_added(name)
super
return unless defined?(@current_attributes)
attributes = {}
kept_attributes = {}
@current_attributes.each do |attribute_name, attribute|
attributes[attribute_name] = attribute[:value]
kept_attributes[attribute_name] = attribute if attribute[:keep]
end
set_attributes(name, attributes)
@current_attributes = kept_attributes
end
def attribute(name, value, options={}, *method_names)
unless options.is_a?(Hash)
method_names << options
options = {}
end
@current_attributes ||= {}
if method_names.empty?
@current_attributes[name] = options.merge(:value => value)
else
method_names.each do |method_name|
set_attributes(method_name, {name => value})
end
end
end
def attributes_table
@attributes_table ||= {}
super.merge(@attributes_table)
end
def set_attributes(method_name, new_attributes)
return if new_attributes.empty?
method_name = normalize_method_name(method_name)
@attributes_table ||= {}
@attributes_table[method_name] ||= {}
current_attributes = @attributes_table[method_name]
new_attributes.each do |key, value|
key = normalize_attribute_name(key)
observers = attribute_observers(key) || []
observers.each do |observer|
observer.call(self,
key,
(attributes(method_name) || {})[key],
value,
method_name)
end
current_attributes[key] = value
end
end
def attributes(method_name)
method_name = normalize_method_name(method_name)
attributes = attributes_table[method_name]
ancestors[1..-1].each do |ancestor|
if ancestor.is_a?(Class) and ancestor < Test::Unit::Attribute
parent_attributes = ancestor.attributes(method_name)
if attributes
attributes = (parent_attributes || {}).merge(attributes)
else
attributes = parent_attributes
end
break
end
end
attributes
end
def get_attribute(method_name, attribute_name)
attribute_name = normalize_attribute_name(attribute_name)
(attributes(method_name) || {})[attribute_name]
end
@@attribute_observers = {}
def register_attribute_observer(attribute_name, observer=Proc.new)
attribute_name = normalize_attribute_name(attribute_name)
@@attribute_observers[attribute_name] ||= []
@@attribute_observers[attribute_name] << observer
end
def attribute_observers(attribute_name)
attribute_name = normalize_attribute_name(attribute_name)
@@attribute_observers[attribute_name]
end
private
def normalize_attribute_name(name)
name.to_s
end
def normalize_method_name(name)
name.to_s
end
end
def attributes
self.class.attributes(@method_name) || {}
end
def [](name)
self.class.get_attribute(@method_name, name)
end
end
end
end
--- NEW FILE: autorunner.rb ---
require 'test/unit'
require 'optparse'
module Test
module Unit
class AutoRunner
RUNNERS = {}
COLLECTORS = {}
ADDITIONAL_OPTIONS = []
class << self
def register_runner(id, runner_builder=Proc.new)
RUNNERS[id] = runner_builder
end
def register_collector(id, collector_builder=Proc.new)
COLLECTORS[id] = collector_builder
end
def setup_option(option_builder=Proc.new)
ADDITIONAL_OPTIONS << option_builder
end
end
def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
r = new(force_standalone || standalone?, &block)
r.base = default_dir
r.process_args(argv)
r.run
end
def self.standalone?
return false unless("-e" == $0)
ObjectSpace.each_object(Class) do |klass|
return false if(klass < TestCase)
end
true
end
register_collector(:descendant) do |auto_runner|
require 'test/unit/collector/descendant'
collector = Collector::Descendant.new
collector.filter = auto_runner.filters
collector.collect($0.sub(/\.rb\Z/, ''))
end
register_collector(:load) do |auto_runner|
require 'test/unit/collector/load'
collector = Collector::Load.new
collector.patterns.concat(auto_runner.pattern) if auto_runner.pattern
collector.excludes.concat(auto_runner.exclude) if auto_runner.exclude
collector.base = auto_runner.base
collector.filter = auto_runner.filters
collector.collect(*auto_runner.to_run)
end
# deprecated
register_collector(:object_space) do |auto_runner|
require 'test/unit/collector/objectspace'
c = Collector::ObjectSpace.new
c.filter = auto_runner.filters
c.collect($0.sub(/\.rb\Z/, ''))
end
# deprecated
register_collector(:dir) do |auto_runner|
require 'test/unit/collector/dir'
c = Collector::Dir.new
c.filter = auto_runner.filters
c.pattern.concat(auto_runner.pattern) if auto_runner.pattern
c.exclude.concat(auto_runner.exclude) if auto_runner.exclude
c.base = auto_runner.base
$:.push(auto_runner.base) if auto_runner.base
c.collect(*(auto_runner.to_run.empty? ? ['.'] : auto_runner.to_run))
end
attr_reader :suite, :runner_options
attr_accessor :filters, :to_run, :pattern, :exclude, :base, :workdir
attr_writer :runner, :collector
def initialize(standalone)
Unit.run = true
@standalone = standalone
@runner = default_runner
@collector = default_collector
@filters = []
@to_run = []
@runner_options = {}
@workdir = nil
yield(self) if block_given?
end
def process_args(args = ARGV)
begin
options.order!(args) {|arg| @to_run << arg}
rescue OptionParser::ParseError => e
puts e
puts options
$! = nil
abort
else
@filters << proc{false} unless(@filters.empty?)
end
not @to_run.empty?
end
def options
@options ||= OptionParser.new do |o|
o.banner = "Test::Unit automatic runner."
o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
o.on
o.on('-r', '--runner=RUNNER', RUNNERS,
"Use the given RUNNER.",
"(" + keyword_display(RUNNERS) + ")") do |r|
@runner = r
end
if(@standalone)
o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
@base = b
end
o.on('-w', '--workdir=DIR', "Working directory to run tests.") do |w|
@workdir = w
end
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
@pattern = []
o.on('-p', '--pattern=PATTERN', Regexp,
"Match files to collect against PATTERN.") do |e|
@pattern << e
end
@exclude = []
o.on('-x', '--exclude=PATTERN', Regexp,
"Ignore files to collect against PATTERN.") do |e|
@exclude << e
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
priority_filter = Proc.new do |test|
if @filters.size > 2
nil
else
Priority::Checker.new(test).need_to_run? or nil
end
end
o.on("--[no-]priority-mode",
"Runs some tests based on their priority.") do |priority_mode|
if priority_mode
@filters |= [priority_filter]
else
@filters -= [priority_filter]
end
end
o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
"Appends directory list to $LOAD_PATH.") do |dirs|
$LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
end
ADDITIONAL_OPTIONS.each do |option_builder|
option_builder.call(self, o)
end
o.on('--',
"Stop processing options so that the",
"remaining options will be passed to the",
"test."){o.terminate}
o.on('-h', '--help', 'Display this help.'){puts o; exit}
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
if RUNNERS[:fox]
o.on_tail('--fox', 'Fox runner (use --runner).') do
warn("Deprecated option (--fox).")
@runner = RUNNERS[:fox]
end
end
o.on_tail
end
end
def keyword_display(array)
list = array.collect {|e, *| e.to_s}
Array === array or list.sort!
list.collect {|e| e.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')}.join(", ")
end
def run
suite = @collector[self]
return false if suite.nil?
runner = @runner[self]
return false if runner.nil?
Dir.chdir(@workdir) if @workdir
runner.run(suite, @runner_options).passed?
end
private
def default_runner
if ENV["EMACS"] == "t"
RUNNERS[:emacs]
else
RUNNERS[:console]
end
end
def default_collector
COLLECTORS[@standalone ? :load : :descendant]
end
end
end
end
require 'test/unit/runner/console'
require 'test/unit/runner/emacs'
--- NEW FILE: collector.rb ---
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
--- NEW FILE: color.rb ---
module Test
module Unit
class Color
NAMES = ["black", "red", "green", "yellow",
"blue", "magenta", "cyan", "white"]
def initialize(name, options={})
@name = name
@foreground = options[:foreground]
@foreground = true if @foreground.nil?
@intensity = options[:intensity]
@bold = options[:bold]
@italic = options[:italic]
@underline = options[:underline]
end
def sequence
sequence = []
if @name == "none"
elsif @name == "reset"
sequence << "0"
else
foreground_parameter = @foreground ? 3 : 4
foreground_parameter += 6 if @intensity
sequence << "#{foreground_parameter}#{NAMES.index(@name)}"
end
sequence << "1" if @bold
sequence << "3" if @italic
sequence << "4" if @underline
sequence
end
def escape_sequence
"\e[#{sequence.join(';')}m"
end
def +(other)
MixColor.new([self, other])
end
end
class MixColor
def initialize(colors)
@colors = colors
end
def sequence
@colors.inject([]) do |result, color|
result + color.sequence
end
end
def escape_sequence
"\e[#{sequence.join(';')}m"
end
def +(other)
self.class.new([self, other])
end
end
end
end
--- NEW FILE: diff.rb ---
# port of Python's difflib.
module Test
module Unit
module Diff
class SequenceMatcher
def initialize(from, to, &junk_predicate)
@from = from
@to = to
@junk_predicate = junk_predicate
update_to_indexes
end
def longest_match(from_start, from_end, to_start, to_end)
best_info = find_best_match_position(from_start, from_end,
to_start, to_end)
unless @junks.empty?
args = [from_start, from_end, to_start, to_end]
best_info = adjust_best_info_with_junk_predicate(false, best_info,
*args)
best_info = adjust_best_info_with_junk_predicate(true, best_info,
*args)
end
best_info
end
def blocks
@blocks ||= compute_blocks
end
def operations
@operations ||= compute_operations
end
def grouped_operations(context_size=nil)
context_size ||= 3
_operations = operations
_operations = [[:equal, 0, 0, 0, 0]] if _operations.empty?
expand_edge_equal_operations!(_operations, context_size)
group_window = context_size * 2
groups = []
group = []
_operations.each do |tag, from_start, from_end, to_start, to_end|
if tag == :equal and from_end - from_start > group_window
group << [tag,
from_start,
[from_end, from_start + context_size].min,
to_start,
[to_end, to_start + context_size].min]
groups << group
group = []
from_start = [from_start, from_end - context_size].max
to_start = [to_start, to_end - context_size].max
end
group << [tag, from_start, from_end, to_start, to_end]
end
groups << group unless group.empty?
groups
end
def ratio
@ratio ||= compute_ratio
end
private
def update_to_indexes
@to_indexes = {}
@junks = {}
if @to.is_a?(String)
each = " "[0].is_a?(Integer) ? :each_byte : :each_char
else
each = :each
end
i = 0
@to.send(each) do |item|
@to_indexes[item] ||= []
@to_indexes[item] << i
i += 1
end
return if @junk_predicate.nil?
@to_indexes = @to_indexes.reject do |key, value|
junk = @junk_predicate.call(key)
@junks[key] = true if junk
junk
end
end
def find_best_match_position(from_start, from_end, to_start, to_end)
best_from, best_to, best_size = from_start, to_start, 0
sizes = {}
from_start.upto(from_end) do |from_index|
_sizes = {}
(@to_indexes[@from[from_index]] || []).each do |to_index|
next if to_index < to_start
break if to_index > to_end
size = _sizes[to_index] = (sizes[to_index - 1] || 0) + 1
if size > best_size
best_from = from_index - size + 1
best_to = to_index - size + 1
best_size = size
end
end
sizes = _sizes
end
[best_from, best_to, best_size]
end
def adjust_best_info_with_junk_predicate(should_junk, best_info,
from_start, from_end,
to_start, to_end)
best_from, best_to, best_size = best_info
while best_from > from_start and best_to > to_start and
(should_junk ?
@junks.has_key?(@to[best_to - 1]) :
!@junks.has_key?(@to[best_to - 1])) and
@from[best_from - 1] == @to[best_to - 1]
best_from -= 1
best_to -= 1
best_size += 1
end
while best_from + best_size < from_end and
best_to + best_size < to_end and
(should_junk ?
@junks.has_key?(@to[best_to + best_size]) :
!@junks.has_key?(@to[best_to + best_size])) and
@from[best_from + best_size] == @to[best_to + best_size]
best_size += 1
end
[best_from, best_to, best_size]
end
def matches
@matches ||= compute_matches
end
def compute_matches
matches = []
queue = [[0, @from.size, 0, @to.size]]
until queue.empty?
from_start, from_end, to_start, to_end = queue.pop
match = longest_match(from_start, from_end - 1, to_start, to_end - 1)
match_from_index, match_to_index, size = match
unless size.zero?
if from_start < match_from_index and
to_start < match_to_index
queue.push([from_start, match_from_index,
to_start, match_to_index])
end
matches << match
if match_from_index + size < from_end and
match_to_index + size < to_end
queue.push([match_from_index + size, from_end,
match_to_index + size, to_end])
end
end
end
matches.sort_by do |(from_index, to_index, match_size)|
from_index
end
end
def compute_blocks
blocks = []
current_from_index = current_to_index = current_size = 0
matches.each do |from_index, to_index, size|
if current_from_index + current_size == from_index and
current_to_index + current_size == to_index
current_size += size
else
unless current_size.zero?
blocks << [current_from_index, current_to_index, current_size]
end
current_from_index = from_index
current_to_index = to_index
current_size = size
end
end
unless current_size.zero?
blocks << [current_from_index, current_to_index, current_size]
end
blocks << [@from.size, @to.size, 0]
blocks
end
def compute_operations
from_index = to_index = 0
operations = []
blocks.each do |match_from_index, match_to_index, size|
tag = determine_tag(from_index, to_index,
match_from_index, match_to_index)
if tag != :equal
operations << [tag,
from_index, match_from_index,
to_index, match_to_index]
end
from_index, to_index = match_from_index + size, match_to_index + size
if size > 0
operations << [:equal,
match_from_index, from_index,
match_to_index, to_index]
end
end
operations
end
def compute_ratio
matches = blocks.inject(0) {|result, block| result + block[-1]}
length = @from.length + @to.length
if length.zero?
1.0
else
2.0 * matches / length
end
end
def determine_tag(from_index, to_index,
match_from_index, match_to_index)
if from_index < match_from_index and to_index < match_to_index
:replace
elsif from_index < match_from_index
:delete
elsif to_index < match_to_index
:insert
else
:equal
end
end
def expand_edge_equal_operations!(_operations, context_size)
tag, from_start, from_end, to_start, to_end = _operations[0]
if tag == :equal
_operations[0] = [tag,
[from_start, from_end - context_size].max,
from_end,
[to_start, to_end - context_size].max,
to_end]
end
tag, from_start, from_end, to_start, to_end = _operations[-1]
if tag == :equal
_operations[-1] = [tag,
from_start,
[from_end, from_start + context_size].min,
to_start,
[to_end, to_start + context_size].min]
end
end
end
class Differ
def initialize(from, to)
@from = from
@to = to
end
private
def tag(mark, contents)
contents.collect {|content| "#{mark}#{content}"}
end
end
class ReadableDiffer < Differ
def diff(options={})
result = []
matcher = SequenceMatcher.new(@from, @to)
matcher.operations.each do |args|
tag, from_start, from_end, to_start, to_end = args
case tag
when :replace
result.concat(diff_lines(from_start, from_end, to_start, to_end))
when :delete
result.concat(tag_deleted(@from[from_start...from_end]))
when :insert
result.concat(tag_inserted(@to[to_start...to_end]))
when :equal
result.concat(tag_equal(@from[from_start...from_end]))
else
raise "unknown tag: #{tag}"
end
end
result
end
private
def tag_deleted(contents)
tag("- ", contents)
end
def tag_inserted(contents)
tag("+ ", contents)
end
def tag_equal(contents)
tag(" ", contents)
end
def tag_difference(contents)
tag("? ", contents)
end
def find_diff_line_info(from_start, from_end, to_start, to_end)
best_ratio = 0.74
from_equal_index = to_equal_index = nil
from_best_index = to_best_index = nil
to_start.upto(to_end - 1) do |to_index|
from_start.upto(from_end - 1) do |from_index|
if @from[from_index] == @to[to_index]
from_equal_index ||= from_index
to_equal_index ||= to_index
next
end
matcher = SequenceMatcher.new(@from[from_index], @to[to_index],
&method(:space_character?))
if matcher.ratio > best_ratio
best_ratio = matcher.ratio
from_best_index = from_index
to_best_index = to_index
end
end
end
[best_ratio,
from_equal_index, to_equal_index,
from_best_index, to_best_index]
end
def diff_lines(from_start, from_end, to_start, to_end)
cut_off = 0.75
info = find_diff_line_info(from_start, from_end, to_start, to_end)
best_ratio, from_equal_index, to_equal_index, *info = info
from_best_index, to_best_index = info
if best_ratio < cut_off
if from_equal_index.nil?
tagged_from = tag_deleted(@from[from_start...from_end])
tagged_to = tag_inserted(@to[to_start...to_end])
if to_end - to_start < from_end - from_start
return tagged_to + tagged_from
else
return tagged_from + tagged_to
end
end
from_best_index = from_equal_index
to_best_index = to_equal_index
best_ratio = 1.0
end
_diff_lines(from_start, from_best_index, to_start, to_best_index) +
diff_line(@from[from_best_index], @to[to_best_index]) +
_diff_lines(from_best_index + 1, from_end, to_best_index + 1, to_end)
end
def _diff_lines(from_start, from_end, to_start, to_end)
if from_start < from_end
if to_start < to_end
diff_lines(from_start, from_end, to_start, to_end)
else
tag_deleted(@from[from_start...from_end])
end
else
tag_inserted(@to[to_start...to_end])
end
end
def diff_line(from_line, to_line)
from_tags = ""
to_tags = ""
matcher = SequenceMatcher.new(from_line, to_line,
&method(:space_character?))
operations = matcher.operations
operations.each do |tag, from_start, from_end, to_start, to_end|
from_length = from_end - from_start
to_length = to_end - to_start
case tag
when :replace
from_tags << "^" * from_length
to_tags << "^" * to_length
when :delete
from_tags << "-" * from_length
when :insert
to_tags << "+" * to_length
when :equal
from_tags << " " * from_length
to_tags << " " * to_length
else
raise "unknown tag: #{tag}"
end
end
format_diff_point(from_line, to_line, from_tags, to_tags)
end
def format_diff_point(from_line, to_line, from_tags, to_tags)
common = [n_leading_characters(from_line, ?\t),
n_leading_characters(to_line, ?\t)].min
common = [common,
n_leading_characters(from_tags[0, common], " "[0])].min
from_tags = from_tags[common..-1].rstrip
to_tags = to_tags[common..-1].rstrip
result = tag_deleted([from_line])
unless from_tags.empty?
result.concat(tag_difference(["#{"\t" * common}#{from_tags}"]))
end
result.concat(tag_inserted([to_line]))
unless to_tags.empty?
result.concat(tag_difference(["#{"\t" * common}#{to_tags}"]))
end
result
end
def n_leading_characters(string, character)
n = 0
while string[n] == character
n += 1
end
n
end
def space_character?(character)
[" "[0], "\t"[0]].include?(character)
end
end
class UnifiedDiffer < Differ
def diff(options={})
groups = SequenceMatcher.new(@from, @to).grouped_operations
return [] if groups.empty?
return [] if same_content?(groups)
show_context = options[:show_context]
show_context = true if show_context.nil?
result = ["--- #{options[:from_label]}".rstrip,
"+++ #{options[:to_label]}".rstrip]
groups.each do |operations|
result << format_summary(operations, show_context)
operations.each do |args|
operation_tag, from_start, from_end, to_start, to_end = args
case operation_tag
when :replace
result.concat(tag("-", @from[from_start...from_end]))
result.concat(tag("+", @to[to_start...to_end]))
when :delete
result.concat(tag("-", @from[from_start...from_end]))
when :insert
result.concat(tag("+", @to[to_start...to_end]))
when :equal
result.concat(tag(" ", @from[from_start...from_end]))
end
end
end
result
end
private
def same_content?(groups)
return false if groups.size != 1
group = groups[0]
return false if group.size != 1
tag, from_start, from_end, to_start, to_end = group[0]
tag == :equal and [from_start, from_end] == [to_start, to_end]
end
def format_summary(operations, show_context)
_, first_from_start, _, first_to_start, _ = operations[0]
_, _, last_from_end, _, last_to_end = operations[-1]
summary = "@@ -%d,%d +%d,%d @@" % [first_from_start + 1,
last_from_end - first_from_start,
first_to_start + 1,
last_to_end - first_to_start,]
if show_context
interesting_line = find_interesting_line(first_from_start,
first_to_start,
:define_line?)
summary << " #{interesting_line}" if interesting_line
end
summary
end
def find_interesting_line(from_start, to_start, predicate)
from_index = from_start
to_index = to_start
while from_index >= 0 or to_index >= 0
[@from[from_index], @to[to_index]].each do |line|
return line if line and send(predicate, line)
end
from_index -= 1
to_index -= 1
end
nil
end
def define_line?(line)
/\A(?:[_a-zA-Z$]|\s*(?:class|module|def)\b)/ =~ line
end
end
module_function
def readable(from, to, options={})
diff(ReadableDiffer, from, to, options)
end
def unified(from, to, options={})
diff(UnifiedDiffer, from, to, options)
end
def diff(differ_class, from, to, options={})
differ = differ_class.new(from.split(/\r?\n/), to.split(/\r?\n/))
differ.diff(options).join("\n")
end
end
end
end
--- NEW FILE: error.rb ---
#--
#
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
require 'test/unit/util/backtracefilter'
module Test
module Unit
# Encapsulates an error in a test. Created by
# Test::Unit::TestCase when it rescues an exception thrown
# during the processing of a test.
class Error
include Util::BacktraceFilter
attr_reader(:test_name, :exception)
SINGLE_CHARACTER = 'E'
LABEL = "Error"
# Creates a new Error with the given test_name and
# exception.
def initialize(test_name, exception)
@test_name = test_name
@exception = exception
end
# Returns a single character representation of an error.
def single_character_display
SINGLE_CHARACTER
end
def label
LABEL
end
# Returns the message associated with the error.
def message
"#{@exception.class.name}: #{@exception.message}"
end
# Returns a brief version of the error description.
def short_display
"#@test_name: #{message.split("\n")[0]}"
end
# Returns a verbose version of the error description.
def long_display
backtrace_display = backtrace.join("\n ")
"#{label}:\n#@test_name:\n#{message}\n #{backtrace_display}"
end
def backtrace
filter_backtrace(@exception.backtrace)
end
# Overridden to return long_display.
def to_s
long_display
end
end
module ErrorHandler
class << self
def included(base)
base.exception_handler(:handle_all_exception)
end
end
PASS_THROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
SystemExit]
private
def handle_all_exception(exception)
case exception
when *PASS_THROUGH_EXCEPTIONS
false
else
problem_occurred
add_error(exception)
true
end
end
def add_error(exception)
current_result.add_error(Error.new(name, exception))
end
end
module TestResultErrorSupport
attr_reader :errors
# Records a Test::Unit::Error.
def add_error(error)
@errors << error
notify_fault(error)
notify_changed
end
# Returns the number of errors this TestResult has
# recorded.
def error_count
@errors.size
end
def error_occurred?
not @errors.empty?
end
private
def initialize_containers
super
@errors = []
@summary_generators << :error_summary
@problem_checkers << :error_occurred?
end
def error_summary
"#{error_count} errors"
end
end
end
end
--- NEW FILE: exceptionhandler.rb ---
module Test
module Unit
module ExceptionHandler
@@exception_handlers = []
class << self
def exception_handlers
@@exception_handlers
end
def included(base)
base.extend(ClassMethods)
observer = Proc.new do |test_case, _, _, value, method_name|
if value
@@exception_handlers.unshift(method_name)
else
@@exception_handlers -= [method_name]
end
end
base.register_attribute_observer(:exception_handler, &observer)
end
end
module ClassMethods
def exception_handlers
ExceptionHandler.exception_handlers
end
def exception_handler(*method_names)
attribute(:exception_handler, true, *method_names)
end
def unregister_exception_handler(*method_names)
attribute(:exception_handler, false, *method_names)
end
end
end
end
end
--- NEW FILE: failure.rb ---
#--
#
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
module Test
module Unit
# Encapsulates a test failure. Created by Test::Unit::TestCase
# when an assertion fails.
class Failure
attr_reader :test_name, :location, :message
SINGLE_CHARACTER = 'F'
LABEL = "Failure"
# Creates a new Failure with the given location and
# message.
def initialize(test_name, location, message)
@test_name = test_name
@location = location
@message = message
end
# Returns a single character representation of a failure.
def single_character_display
SINGLE_CHARACTER
end
def label
LABEL
end
# Returns a brief version of the error description.
def short_display
"#@test_name: #{@message.split("\n")[0]}"
end
# Returns a verbose version of the error description.
def long_display
if location.size == 1
location_display = location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
else
location_display = "\n [#{location.join("\n ")}]"
end
"#{label}:\n#@test_name#{location_display}:\n#@message"
end
# Overridden to return long_display.
def to_s
long_display
end
end
module FailureHandler
class << self
def included(base)
base.exception_handler(:handle_assertion_failed_error)
end
end
private
def handle_assertion_failed_error(exception)
return false unless exception.is_a?(AssertionFailedError)
problem_occurred
add_failure(exception.message, exception.backtrace)
true
end
def add_failure(message, backtrace)
failure = Failure.new(name, filter_backtrace(backtrace), message)
current_result.add_failure(failure)
end
end
module TestResultFailureSupport
attr_reader :failures
# Records a Test::Unit::Failure.
def add_failure(failure)
@failures << failure
notify_fault(failure)
notify_changed
end
# Returns the number of failures this TestResult has
# recorded.
def failure_count
@failures.size
end
def failure_occurred?
not @failures.empty?
end
private
def initialize_containers
super
@failures = []
@summary_generators << :failure_summary
@problem_checkers << :failure_occurred?
end
def failure_summary
"#{failure_count} failures"
end
end
end
end
--- NEW FILE: fixture.rb ---
module Test
module Unit
module Fixture
class << self
def included(base)
base.extend(ClassMethods)
[:setup, :teardown].each do |fixture|
observer = Proc.new do |test_case, _, _, value, method_name|
if value.nil?
test_case.send("unregister_#{fixture}_method", method_name)
else
test_case.send("register_#{fixture}_method", method_name,
value)
end
end
base.register_attribute_observer(fixture, &observer)
end
end
end
module ClassMethods
def setup(*method_names)
register_fixture(:setup, *method_names)
end
def unregister_setup(*method_names)
unregister_fixture(:setup, *method_names)
end
def teardown(*method_names)
register_fixture(:teardown, *method_names)
end
def unregister_teardown(*method_names)
unregister_fixture(:teardown, *method_names)
end
def register_setup_method(method_name, options)
register_fixture_method(:setup, method_name, options, :after, :append)
end
def unregister_setup_method(method_name)
unregister_fixture_method(:setup, method_name)
end
def register_teardown_method(method_name, options)
register_fixture_method(:teardown, method_name, options,
:before, :prepend)
end
def unregister_teardown_method(method_name)
unregister_fixture_method(:teardown, method_name)
end
def before_setup_methods
collect_fixture_methods(:setup, :before)
end
def after_setup_methods
collect_fixture_methods(:setup, :after)
end
def before_teardown_methods
collect_fixture_methods(:teardown, :before)
end
def after_teardown_methods
collect_fixture_methods(:teardown, :after)
end
private
def register_fixture(fixture, *method_names)
options = {}
options = method_names.pop if method_names.last.is_a?(Hash)
attribute(fixture, options, *method_names)
end
def unregister_fixture(fixture, *method_names)
attribute(fixture, nil, *method_names)
end
def valid_register_fixture_options?(options)
return true if options.empty?
return false if options.size > 1
key = options.keys.first
[:before, :after].include?(key) and
[:prepend, :append].include?(options[key])
end
def add_fixture_method_name(how, variable_name, method_name)
unless self.instance_variable_defined?(variable_name)
self.instance_variable_set(variable_name, [])
end
methods = self.instance_variable_get(variable_name)
if how == :prepend
methods = [method_name] | methods
else
methods = methods | [method_name]
end
self.instance_variable_set(variable_name, methods)
end
def registered_methods_variable_name(fixture, order)
"@#{order}_#{fixture}_methods"
end
def unregistered_methods_variable_name(fixture)
"@unregistered_#{fixture}_methods"
end
def register_fixture_method(fixture, method_name, options,
default_order, default_how)
unless valid_register_fixture_options?(options)
message = "must be {:before => :prepend}, " +
"{:before => :append}, {:after => :prepend} or " +
"{:after => :append}: #{options.inspect}"
raise ArgumentError, message
end
if options.empty?
order, how = default_order, default_how
else
order, how = options.to_a.first
end
variable_name = registered_methods_variable_name(fixture, order)
add_fixture_method_name(how, variable_name, method_name)
end
def unregister_fixture_method(fixture, method_name)
variable_name = unregistered_methods_variable_name(fixture)
add_fixture_method_name(:append, variable_name, method_name)
end
def collect_fixture_methods(fixture, order)
methods_variable = registered_methods_variable_name(fixture, order)
unregistered_methods_variable =
unregistered_methods_variable_name(fixture)
base_index = ancestors.index(Fixture)
interested_ancestors = ancestors[0, base_index].reverse
interested_ancestors.inject([]) do |result, ancestor|
if ancestor.is_a?(Class)
ancestor.class_eval do
methods = []
unregistered_methods = []
if instance_variable_defined?(methods_variable)
methods = instance_variable_get(methods_variable)
end
if instance_variable_defined?(unregistered_methods_variable)
unregistered_methods =
instance_variable_get(unregistered_methods_variable)
end
(result | methods) - unregistered_methods
end
else
result
end
end
end
end
private
def run_fixture(fixture)
[
self.class.send("before_#{fixture}_methods"),
fixture,
self.class.send("after_#{fixture}_methods")
].flatten.each do |method_name|
send(method_name) if respond_to?(method_name, true)
end
end
def run_setup
run_fixture(:setup)
end
def run_teardown
run_fixture(:teardown)
end
end
end
end
--- NEW FILE: notification.rb ---
require 'test/unit/util/backtracefilter'
module Test
module Unit
class Notification
include Util::BacktraceFilter
attr_reader :test_name, :location, :message
SINGLE_CHARACTER = 'N'
LABEL = "Notification"
# Creates a new Notification with the given location and
# message.
def initialize(test_name, location, message)
@test_name = test_name
@location = location
@message = message
end
# Returns a single character representation of a notification.
def single_character_display
SINGLE_CHARACTER
end
def label
LABEL
end
# Returns a brief version of the error description.
def short_display
"#{@test_name}: #{@message.split("\n")[0]}"
end
# Returns a verbose version of the error description.
def long_display
backtrace = filter_backtrace(location).join("\n")
"#{label}: #{@message}\n#{@test_name}\n#{backtrace}"
end
# Overridden to return long_display.
def to_s
long_display
end
end
class NotifiedError < StandardError
end
module TestCaseNotificationSupport
class << self
def included(base)
base.class_eval do
include NotificationHandler
end
end
end
# Notify some information.
#
# Example:
# def test_notification
# notify("I'm here!")
# # Reached here
# notify("Special!") if special_case?
# # Reached here too
# end
def notify(message, &block)
notification = Notification.new(name, filter_backtrace(caller), message)
add_notification(notification)
end
private
def add_notification(notification)
current_result.add_notification(notification)
end
end
module NotificationHandler
class << self
def included(base)
base.exception_handler(:handle_Notified_error)
end
end
private
def handle_Notified_error(exception)
return false unless exception.is_a?(NotifiedError)
notification = Notification.new(name,
filter_backtrace(exception.backtrace),
exception.message)
add_notification(notification)
true
end
end
module TestResultNotificationSupport
attr_reader :notifications
# Records a Test::Unit::Notification.
def add_notification(notification)
@notifications << notification
notify_fault(notification)
notify_changed
end
# Returns the number of notifications this TestResult has
# recorded.
def notification_count
@notifications.size
end
private
def initialize_containers
super
@notifications = []
@summary_generators << :notification_summary
end
def notification_summary
"#{notification_count} notifications"
end
end
end
end
--- NEW FILE: omission.rb ---
require 'test/unit/util/backtracefilter'
module Test
module Unit
class Omission
include Util::BacktraceFilter
attr_reader :test_name, :location, :message
SINGLE_CHARACTER = 'O'
LABEL = "Omission"
# Creates a new Omission with the given location and
# message.
def initialize(test_name, location, message)
@test_name = test_name
@location = location
@message = message
end
# Returns a single character representation of a omission.
def single_character_display
SINGLE_CHARACTER
end
def label
LABEL
end
# Returns a brief version of the error description.
def short_display
"#{@test_name}: #{@message.split("\n")[0]}"
end
# Returns a verbose version of the error description.
def long_display
backtrace = filter_backtrace(location).join("\n")
"#{label}: #{@message}\n#{@test_name}\n#{backtrace}"
end
# Overridden to return long_display.
def to_s
long_display
end
end
class OmittedError < StandardError
end
module TestCaseOmissionSupport
class << self
def included(base)
base.class_eval do
include OmissionHandler
end
end
end
# Omit the test of part of the test.
#
# Example:
# def test_omission
# omit
# # Not reached here
# end
#
# def test_omission_with_here
# omit do
# # Not ran here
# end
# # Reached here
# end
def omit(message=nil, &block)
message ||= "omitted."
if block_given?
omission = Omission.new(name, filter_backtrace(caller), message)
add_omission(omission)
else
raise OmittedError.new(message)
end
end
def omit_if(condition, *args, &block)
omit(*args, &block) if condition
end
def omit_unless(condition, *args, &block)
omit(*args, &block) unless condition
end
private
def add_omission(omission)
current_result.add_omission(omission)
end
end
module OmissionHandler
class << self
def included(base)
base.exception_handler(:handle_omitted_error)
end
end
private
def handle_omitted_error(exception)
return false unless exception.is_a?(OmittedError)
omission = Omission.new(name,
filter_backtrace(exception.backtrace),
exception.message)
add_omission(omission)
true
end
end
module TestResultOmissionSupport
attr_reader :omissions
# Records a Test::Unit::Omission.
def add_omission(omission)
@omissions << omission
notify_fault(omission)
notify_changed
end
# Returns the number of omissions this TestResult has
# recorded.
def omission_count
@omissions.size
end
private
def initialize_containers
super
@omissions = []
@summary_generators << :omission_summary
end
def omission_summary
"#{omission_count} omissions"
end
end
end
end
--- NEW FILE: pending.rb ---
require 'test/unit/util/backtracefilter'
module Test
module Unit
class Pending
include Util::BacktraceFilter
attr_reader :test_name, :location, :message
SINGLE_CHARACTER = 'P'
LABEL = "Pending"
# Creates a new Pending with the given location and
# message.
def initialize(test_name, location, message)
@test_name = test_name
@location = location
@message = message
end
# Returns a single character representation of a pending.
def single_character_display
SINGLE_CHARACTER
end
def label
LABEL
end
# Returns a brief version of the error description.
def short_display
"#{@test_name}: #{@message.split("\n")[0]}"
end
# Returns a verbose version of the error description.
def long_display
backtrace = filter_backtrace(location).join("\n")
"#{label}: #{@message}\n#{@test_name}\n#{backtrace}"
end
# Overridden to return long_display.
def to_s
long_display
end
end
class PendedError < StandardError
end
module TestCasePendingSupport
class << self
def included(base)
base.class_eval do
include PendingHandler
end
end
end
# Marks the test or part of the test is pending.
#
# Example:
# def test_pending
# pend
# # Not reached here
# end
#
# def test_pending_with_here
# pend do
# # Ran here
# # Fails if the block doesn't raise any error.
# # Because it means the block is passed unexpectedly.
# end
# # Reached here
# end
def pend(message=nil, &block)
message ||= "pended."
if block_given?
pending = nil
begin
yield
rescue Exception
pending = Pending.new(name, filter_backtrace(caller), message)
add_pending(pending)
end
unless pending
flunk("Pending block should not be passed: #{message}")
end
else
raise PendedError.new(message)
end
end
private
def add_pending(pending)
problem_occurred
current_result.add_pending(pending)
end
end
module PendingHandler
class << self
def included(base)
base.exception_handler(:handle_pended_error)
end
end
private
def handle_pended_error(exception)
return false unless exception.is_a?(PendedError)
pending = Pending.new(name,
filter_backtrace(exception.backtrace),
exception.message)
add_pending(pending)
true
end
end
module TestResultPendingSupport
attr_reader :pendings
# Records a Test::Unit::Pending.
def add_pending(pending)
@pendings << pending
notify_fault(pending)
notify_changed
end
# Returns the number of pendings this TestResult has
# recorded.
def pending_count
@pendings.size
end
private
def initialize_containers
super
@pendings = []
@summary_generators << :pending_summary
end
def pending_summary
"#{pending_count} pendings"
end
end
end
end
--- NEW FILE: priority.rb ---
require "fileutils"
require "tmpdir"
module Test
module Unit
module Priority
class << self
def included(base)
base.extend(ClassMethods)
base.class_eval do
setup :priority_setup, :before => :prepend
teardown :priority_teardown, :after => :append
end
end
end
class Checker
class << self
def have_priority?(name)
singleton_class = (class << self; self; end)
singleton_class.method_defined?(priority_check_method_name(name))
end
def need_to_run?(test)
priority = test[:priority] || :normal
if have_priority?(priority)
send(priority_check_method_name(priority), test)
else
true
end
end
def run_priority_must?(test)
true
end
def run_priority_important?(test)
rand > 0.1
end
def run_priority_high?(test)
rand > 0.3
end
def run_priority_normal?(test)
rand > 0.5
end
def run_priority_low?(test)
rand > 0.75
end
def run_priority_never?(test)
false
end
private
def priority_check_method_name(priority_name)
"run_priority_#{priority_name}?"
end
end
attr_reader :test
def initialize(test)
@test = test
end
def setup
FileUtils.rm_f(passed_file)
end
def teardown
if @test.send(:passed?)
FileUtils.touch(passed_file)
else
FileUtils.rm_f(passed_file)
end
end
def need_to_run?
!previous_test_success? or self.class.need_to_run?(@test)
end
private
def previous_test_success?
File.exist?(passed_file)
end
def result_dir
components = [".test-result",
@test.class.name || "AnonymousTestCase",
@test.method_name.to_s]
parent_directories = [File.dirname($0), Dir.pwd]
if Process.respond_to?(:uid)
parent_directories << File.join(Dir.tmpdir, Process.uid.to_s)
end
parent_directories.each do |parent_directory|
dir = File.expand_path(File.join(parent_directory, *components))
begin
FileUtils.mkdir_p(dir)
return dir
rescue Errno::EACCES
end
end
raise Errno::EACCES, parent_directories.join(", ")
end
def passed_file
File.join(result_dir, "passed")
end
def escaped_method_name
@method_name.to_s.gsub(/[!?=]$/) do |matched|
case matched
when "!"
".destructive"
when "?"
".predicate"
when "="
".equal"
end
end
end
end
module ClassMethods
def priority(name, *tests)
unless Checker.have_priority?(name)
raise ArgumentError, "unknown priority: #{name}"
end
attribute(:priority, name, {:keep => true}, *tests)
end
end
def priority_setup
Checker.new(self).setup
end
def priority_teardown
Checker.new(self).teardown
end
end
end
end
--- NEW FILE: testcase.rb ---
#--
#
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
require 'test/unit/attribute'
require 'test/unit/fixture'
require 'test/unit/exceptionhandler'
require 'test/unit/assertions'
require 'test/unit/failure'
require 'test/unit/error'
require 'test/unit/pending'
require 'test/unit/omission'
require 'test/unit/notification'
require 'test/unit/priority'
require 'test/unit/testsuite'
require 'test/unit/assertionfailederror'
require 'test/unit/util/backtracefilter'
module Test
module Unit
# 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 teardown
# ...
# end
#
# def test_my_method1
# ...
# end
#
# def test_my_method2
# ...
# end
# end
#
# Here is a call order:
# * startup
# * setup
# * test_my_method1
# * teardown
# * setup
# * test_my_method2
# * teardown
# * shutdown
class TestCase
include Attribute
include Fixture
include ExceptionHandler
include ErrorHandler
include FailureHandler
include TestCasePendingSupport
include TestCaseOmissionSupport
include TestCaseNotificationSupport
include Priority
include Assertions
include Util::BacktraceFilter
STARTED = name + "::STARTED"
FINISHED = name + "::FINISHED"
DESCENDANTS = []
class << self
def inherited(sub_class)
DESCENDANTS << sub_class
end
# Rolls up all of the test* methods in the fixture into
# one suite, creating a new instance of the fixture for
# each method.
def suite
method_names = public_instance_methods(true).collect {|name| name.to_s}
tests = method_names.delete_if {|method_name| method_name !~ /^test./}
suite = TestSuite.new(name, self)
tests.sort.each do |test|
catch(:invalid_test) do
suite << new(test)
end
end
if suite.empty?
catch(:invalid_test) do
suite << new("default_test")
end
end
suite
end
end
attr_reader :method_name
# Creates a new instance of the fixture for running the
# test represented by test_method_name.
def initialize(test_method_name)
throw :invalid_test unless respond_to?(test_method_name)
throw :invalid_test if method(test_method_name).arity > 0
@method_name = test_method_name
@test_passed = true
@interrupted = false
end
# Runs the individual test method represented by this
# instance of the fixture, collecting statistics, failures
# and errors in result.
def run(result)
begin
@_result = result
yield(STARTED, name)
begin
run_setup
run_test
rescue Exception
@interrupted = true
raise unless handle_exception($!)
ensure
begin
run_teardown
rescue Exception
raise unless handle_exception($!)
end
end
result.add_run
yield(FINISHED, name)
ensure
@_result = nil
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
# def my_setup2
# ...
# end
#
# def test_my_class
# ...
# end
# end
#
# Here is a call order:
# * setup
# * my_setup1
# * my_setup2
# * test_my_class
def setup
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
# def my_teardown2
# ...
# end
#
# def test_my_class
# ...
# end
# end
#
# Here is a call order:
# * test_my_class
# * my_teardown2
# * my_teardown1
# * teardown
def teardown
end
def default_test
flunk("No tests were specified")
end
def size
1
end
# Returns a human-readable name for the specific test that
# this instance of TestCase represents.
def name
"#{@method_name}(#{self.class.name})"
end
# Overridden to return #name.
def to_s
name
end
# It's handy to be able to compare TestCase instances.
def ==(other)
return false unless(other.kind_of?(self.class))
return false unless(@method_name == other.method_name)
self.class == other.class
end
def interrupted?
@interrupted
end
private
def current_result
@_result
end
def run_test
__send__(@method_name)
end
def handle_exception(exception)
self.class.exception_handlers.each do |handler|
return true if send(handler, exception)
end
false
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.
def passed?
@test_passed
end
def problem_occurred
@test_passed = false
end
def add_assertion
current_result.add_assertion
end
end
end
end
--- NEW FILE: testresult.rb ---
#--
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
require 'test/unit/util/observable'
require 'test/unit/failure'
require 'test/unit/error'
require 'test/unit/omission'
require 'test/unit/pending'
require 'test/unit/notification'
module Test
module Unit
module NullResultContainerInitializer
private
def initialize_containers
end
end
# Collects Test::Unit::Failure and Test::Unit::Error so that
# they can be displayed to the user. To this end, observers
# can be added to it, allowing the dynamic updating of, say, a
# UI.
class TestResult
include Util::Observable
include NullResultContainerInitializer
include TestResultFailureSupport
include TestResultErrorSupport
include TestResultPendingSupport
include TestResultOmissionSupport
include TestResultNotificationSupport
CHANGED = "CHANGED"
FAULT = "FAULT"
attr_reader :run_count, :assertion_count, :faults
# Constructs a new, empty TestResult.
def initialize
@run_count, @assertion_count = 0, 0
@summary_generators = []
@problem_checkers = []
@faults = []
initialize_containers
end
# Records a test run.
def add_run
@run_count += 1
notify_changed
end
# Records an individual assertion.
def add_assertion
@assertion_count += 1
notify_changed
end
# Returns a string contain the recorded runs, assertions,
# failures and errors in this TestResult.
def summary
["#{run_count} tests",
"#{assertion_count} assertions",
*@summary_generators.collect {|generator| send(generator)}].join(", ")
end
def to_s
summary
end
# Returns whether or not this TestResult represents
# successful completion.
def passed?
@problem_checkers.all? {|checker| not send(checker)}
end
private
def notify_changed
notify_listeners(CHANGED, self)
end
def notify_fault(fault)
@faults << fault
notify_listeners(FAULT, fault)
end
end
end
end
--- NEW FILE: testsuite.rb ---
#--
#
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.
require 'test/unit/error'
module Test
module Unit
# A collection of tests which can be #run.
#
# Note: It is easy to confuse a TestSuite instance with
# something that has a static suite method; I know because _I_
# have trouble keeping them straight. Think of something that
# has a suite method as simply providing a way to get a
# meaningful TestSuite instance.
class TestSuite
attr_reader :name, :tests
STARTED = name + "::STARTED"
FINISHED = name + "::FINISHED"
# Creates a new TestSuite with the given name.
def initialize(name="Unnamed TestSuite", test_case=nil)
@name = name
@tests = []
@test_case = test_case
end
# Runs the tests and/or suites contained in this
# TestSuite.
def run(result, &progress_block)
yield(STARTED, name)
run_startup(result)
@tests.each do |test|
test.run(result, &progress_block)
end
run_shutdown(result)
yield(FINISHED, name)
end
# Adds the test to the suite.
def <<(test)
@tests << test
self
end
def delete(test)
@tests.delete(test)
end
# Retuns the rolled up number of tests in this suite;
# i.e. if the suite contains other suites, it counts the
# tests within those suites, not the suites themselves.
def size
total_size = 0
@tests.each { |test| total_size += test.size }
total_size
end
def empty?
tests.empty?
end
# Overridden to return the name given the suite at
# creation.
def to_s
@name
end
# It's handy to be able to compare TestSuite instances.
def ==(other)
return false unless(other.kind_of?(self.class))
return false unless(@name == other.name)
@tests == other.tests
end
private
def run_startup(result)
return if @test_case.nil? or !@test_case.respond_to?(:startup)
begin
@test_case.startup
rescue Exception
raise unless handle_exception($!, result)
end
end
def run_shutdown(result)
return if @test_case.nil? or !@test_case.respond_to?(:shutdown)
begin
@test_case.shutdown
rescue Exception
raise unless handle_exception($!, result)
end
end
def handle_exception(exception, result)
case exception
when *ErrorHandler::PASS_THROUGH_EXCEPTIONS
false
else
result.add_error(Error.new(@test_case.name, exception))
true
end
end
end
end
end
--- NEW FILE: version.rb ---
# HACK: quick and dirty to get integrated into the new project - ryan
module Test
module Unit
VERSION = '2.0.1'
end
end
- Previous message: [cairo-commit] rcairo/test-unit/lib/test unit.rb,NONE,1.1
- Next message: [cairo-commit] rcairo/test-unit/lib/test/unit/collector descendant.rb, NONE, 1.1 dir.rb, NONE, 1.1 load.rb, NONE, 1.1 objectspace.rb, NONE, 1.1
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list