Class: Test::Unit::TestCase
- Inherits:
-
Object
- Object
- Test::Unit::TestCase
- Defined in:
- lib/assert_same.rb
Constant Summary collapse
- @@file_offsets =
Hash[line_number] = offset For each line in the original file we store its offset (+N or -N lines) relative to the actual file
Hash.new { |hash, key| hash[key] = {} }
Instance Method Summary collapse
-
#assert_same(actual, expected = :autofill_expected_value) ⇒ Object
assert_same: assert which checks that two strings (expected and actual) are same and which can “magically” replace expected value with the actual in case the new behavior (and new actual value) is correct.
Instance Method Details
#assert_same(actual, expected = :autofill_expected_value) ⇒ Object
assert_same: assert which checks that two strings (expected and actual) are same and which can “magically” replace expected value with the actual in case the new behavior (and new actual value) is correct
Usage ==
Write this in the test source:
assert_same something, <<-END
foo
bar
zee
END
Then run tests as usual:
rake test:units
ruby test/unit/foo_test.rb
...
When assert_same fails, you’ll be able to:
-
review diff
-
(optionally) accept new actual value (this modifies the test source file)
Additional options for test runs: –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:
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)
-
ruby-style comments after “#” are ignored: both whole-line and end-of-line comments are supported
-
empty lines are ignored
-
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:
rake test TESTOPTS="-- --no-canonicalize --autoaccept"
Example of assert_same with comments:
assert_same something, <<-END
# some tree
foo 1
foo 1.1
foo 1.2 # some node
bar 2
bar 2.1
END
Umportant Usage Rules ==
Restrictions:
-
only END and EOS are supported as end of string sequence
-
it’s a requirement that you have <<-END at the same line as assert_same
-
assert_same can’t be within a block
Storing expected output in files:
-
assert_same something, :log => <path_to_file>
-
path to file is relative to:
-
RAILS_ROOT (if that is defined)
-
current dir (if no RAILS_ROOT is defined)
-
-
file doesn’t have to exist, it will be created if necessary
Misc:
-
it’s ok to have several assert_same’s in the same test method, assert_same. correctly updates all assert_same’s in the test file
-
it’s ok to omit expected string, like this:
assert_same something
in fact, this is the preferred way to create assert_same tests - you write empty assert_same, run tests and they will fill expected values for you automatically
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/assert_same.rb', line 97 def assert_same(actual, expected = :autofill_expected_value) if expected.class == String expected ||= "" mode = :expecting_string elsif expected == :autofill_expected_value expected = "" mode = :autofill_expected_value elsif expected.class == Hash raise ":log key is missing" unless expected.has_key? :log mode = :expecting_file log_file = expected[:log] if defined? RAILS_ROOT log_file = File.(log_file, RAILS_ROOT) else log_file = File.(log_file, Dir.pwd) end expected = File.exists?(log_file) ? File.read(log_file) : "" else internal_error("Incorrect expected argument for assert_same. It must be either String or Hash.") 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") 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}" 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" end if accept if [:expecting_string, :autofill_expected_value].include? mode accept_string(actual, mode) elsif mode == :expecting_file accept_file(actual, log_file) end end 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 else raise Test::Unit::AssertionFailedError.new(diff_to_report) end else add_assertion end end |