lib/assert_same.rb in assert_same-0.2 vs lib/assert_same.rb in assert_same-0.3
- old
+ new
@@ -1,12 +1,58 @@
# Copyright (c) 2010-2011 Pluron, Inc.
require 'test/unit/testcase'
require 'text_diff'
require 'pathname'
-class Test::Unit::TestCase
+$assert_same_options = []
+if RUBY_VERSION >= "1.9.0"
+
+ # Test/Unit from Ruby 1.9 can't accept additional options like it did in 1.8:
+ # ruby test.rb -- --foo
+ # Now it has a strict option parser that considers all additional options as files.
+ # The right way to have an option now is to explicitly add it to Test/Unit parser.
+ module Test::Unit
+
+ module AssertSameOption
+ def setup_options(parser, options)
+ super
+ parser.on '--no-interactive', 'assert_same: non-interactive mode' do |flag|
+ $assert_same_options << "--no-interactive"
+ puts $assert_same_options
+ end
+ parser.on '--no-canonicalize', 'assert_same: turn off canonicalization' do |flag|
+ $assert_same_options << "--no-canonicalize"
+ end
+ parser.on '--autoaccept', 'assert_same: automatically accept new actual values' do |flag|
+ $assert_same_options << "--autoaccept"
+ end
+ end
+
+ def non_options(files, options)
+ super
+ end
+ end
+
+ class Runner < MiniTest::Unit
+ include Test::Unit::AssertSameOption
+ end
+
+ end
+
+else
+
+ # In Ruby 1.8 additional test options are simply passed via ARGV
+ $assert_same_options << "--no-interactive" if ARGV.include?("--no-interactive")
+ $assert_same_options << "--no-canonicalize" if ARGV.include?("--no-canonicalize")
+ $assert_same_options << "--autoaccept" if ARGV.include?("--autoaccept")
+
+end
+
+
+module Test::Unit::Assertions
+
#Hash[filename][line_number] = offset
#For each line in the original file we store its offset (+N or -N lines)
#relative to the actual file
@@file_offsets = Hash.new { |hash, key| hash[key] = {} }
@@ -36,18 +82,25 @@
# --no-interactive skips all questions and just reports failures
# --autoaccept prints diffs and automatically accepts all new actual values
# --no-canonicalize turns off expected and actual value canonicalization (see below for details)
#
# Additional options can be passed during both single test file run and rake test run:
+ # In Ruby 1.8:
# ruby test/unit/foo_test.rb -- --autoaccept
# ruby test/unit/foo_test.rb -- --no-interactive
#
# rake test TESTOPTS="-- --autoaccept"
# rake test:units TESTOPTS="-- --no-canonicalize --autoaccept"
#
+ # In Ruby 1.9:
+ # ruby test/unit/foo_test.rb --autoaccept
+ # ruby test/unit/foo_test.rb --no-interactive
#
+ # rake test TESTOPTS="--autoaccept"
+ # rake test:units TESTOPTS="--no-canonicalize --autoaccept"
#
+ #
# == Canonicalization ==
#
# Before comparing expected and actual strings, assert_same canonicalizes both using these rules:
# - indentation is ignored (except for indentation
# relative to the first line of the expected/actual string)
@@ -57,11 +110,14 @@
# - trailing whitespaces are ignored
#
# You can turn canonicalization off with --no-canonicalize option. This is useful
# when you need to regenerate expected test strings.
# To regenerate the whole test suite, run:
+ # In Ruby 1.8:
# rake test TESTOPTS="-- --no-canonicalize --autoaccept"
+ # In Ruby 1.9:
+ # rake test TESTOPTS="--no-canonicalize --autoaccept"
#
# Example of assert_same with comments:
# assert_same something, <<-END
# # some tree
# foo 1
@@ -116,32 +172,31 @@
end
# interactive mode is turned on by default, except when
# - --no-interactive is given
# - STDIN is not a terminal device (i.e. we can't ask any questions)
- interactive = !ARGV.include?("--no-interactive") && STDIN.tty?
- canonicalize = !ARGV.include?("--no-canonicalize")
- autoaccept = ARGV.include?("--autoaccept")
+ interactive = !$assert_same_options.include?("--no-interactive") && STDIN.tty?
+ canonicalize = !$assert_same_options.include?("--no-canonicalize")
+ autoaccept = $assert_same_options.include?("--autoaccept")
is_same_canonicalized, is_same, diff_canonicalized, diff = compare_for_assert_same(expected, actual)
if (canonicalize and !is_same_canonicalized) or (!canonicalize and !is_same)
diff_to_report = canonicalize ? diff_canonicalized : diff
if interactive
# print method name and short backtrace
- failure = Test::Unit::Failure.new(name, filter_backtrace(caller(0)), diff_to_report)
- puts "\n#{failure}"
+ soft_fail(diff_to_report)
if autoaccept
accept = true
else
print "Accept the new value: yes to all, no to all, yes, no? [Y/N/y/n] (y): "
STDOUT.flush
response = STDIN.gets.strip
accept = ["", "y", "Y"].include? response
- ARGV << "--autoaccept" if response == "Y"
- ARGV << "--no-interactive" if response == "N"
+ $assert_same_options << "--autoaccept" if response == "Y"
+ $assert_same_options << "--no-interactive" if response == "N"
end
if accept
if [:expecting_string, :autofill_expected_value].include? mode
accept_string(actual, mode)
@@ -152,21 +207,47 @@
end
if accept
# when change is accepted, we should not report it as a failure because
# we want the test method to continue executing (in case there're more
# assert_same's in the method)
- add_assertion
+ succeed
else
- raise Test::Unit::AssertionFailedError.new(diff_to_report)
+ fail(diff)
end
else
- add_assertion
+ succeed
end
end
private
+ def succeed
+ if RUBY_VERSION < "1.9.0"
+ add_assertion
+ else
+ true
+ end
+ end
+
+ def soft_fail(diff)
+ if RUBY_VERSION < "1.9.0"
+ failure = Test::Unit::Failure.new(name, filter_backtrace(caller(0)), diff)
+ puts "\n#{failure}"
+ else
+ failure = MiniTest::Assertion.new(diff)
+ puts "\n#{failure}"
+ end
+ end
+
+ def fail(diff)
+ if RUBY_VERSION < "1.9.0"
+ raise Test::Unit::AssertionFailedError.new(diff)
+ else
+ raise MiniTest::Assertion.new(diff)
+ end
+ end
+
def accept_string(actual, mode)
file, method, line = get_caller_location(:depth => 3)
# read source file, construct the new source, replacing everything
# between "do" and "end" in assert_same's block
@@ -207,10 +288,10 @@
actual_length = actual.split("\n").length
actual_length += 1 if mode == :autofill_expected_value # END marker after actual value
@@file_offsets[file][line.to_i] = actual_length - expected_length
source_file = File.open(file, "w+")
- source_file.write(source)
+ source_file.write(source.join(''))
source_file.fsync
source_file.close
end
def accept_file(actual, log_file)