Module: AssertValueAssertion
- Included in:
- BeSameValueAs, MiniTest::Unit::TestCase, Minitest::Test, Test::Unit::TestCase
- Defined in:
- lib/assert_value.rb
Instance Method Summary collapse
-
#assert_value(*args) ⇒ Object
assert_value: 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.
- #be_same_value_as(expected = nil) ⇒ Object
- #file_offsets ⇒ Object
Instance Method Details
#assert_value(*args) ⇒ Object
assert_value: 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_value something, <<-END
foo
bar
zee
END
You can also use assert_value for blocks. Then you can assert block result or raised exception
assert_value(<<-END) do
Exception NoMethodError: undefined method `+' for nil:NilClass
END
# Code block starts here
c = nil + 1
end
Then run tests as usual:
rake test:units
ruby test/unit/foo_test.rb
...
When assert_value 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:
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_value 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:
In Ruby 1.8:
rake test TESTOPTS="-- --no-canonicalize --autoaccept"
In Ruby 1.9:
rake test TESTOPTS="--no-canonicalize --autoaccept"
Example of assert_value with comments:
assert_value 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_value
-
assert_value can’t be within a block
Storing expected output in files:
-
assert_value 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_value’s in the same test method, assert_value. correctly updates all assert_value’s in the test file
-
it’s ok to omit expected string, like this:
assert_value somethingin fact, this is the preferred way to create assert_value tests - you write empty assert_value, run tests and they will fill expected values for you automatically
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/assert_value.rb', line 189 def assert_value(*args) if block_given? # rspec passes block to the expect() function, not to the matcher # so string substitution should work as if assert_value is called with a string mode = @rspec_matcher ? :scalar : :block expected = args[0] actual = "" begin actual = yield.to_s rescue Exception => e actual = "Exception #{e.class}: #{e.}" end else mode = :scalar expected = args[1] actual = args[0] end if expected.nil? expected = "" change = :create_expected_string elsif expected.class == String change = :update_expected_string elsif expected.class == Hash raise ":log key is missing" unless expected.has_key? :log 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.exist?(log_file) ? File.read(log_file) : "" change = :update_file_with_expected_string else internal_error("Invalid expected class #{expected.class}") end # interactive mode is turned on by default, except when # - --no-interactive is given # - CIRCLECI is set (CircleCI captures test output, but doesn't interact with user) # - STDIN is not a terminal device (i.e. we can't ask any questions) interactive = !$assert_value_options.include?("--no-interactive") && !ENV["CIRCLECI"] && STDIN.tty? canonicalize = !$assert_value_options.include?("--no-canonicalize") autoaccept = $assert_value_options.include?("--autoaccept") is_same_canonicalized, is_same, diff_canonicalized, diff = compare_for_assert_value(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 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 $assert_value_options << "--autoaccept" if response == "Y" $assert_value_options << "--no-interactive" if response == "N" end if accept if [:create_expected_string, :update_expected_string].include? change accept_string(actual, change, mode) elsif change == :update_file_with_expected_string accept_file(actual, log_file) else internal_error("Invalid change #{change}") 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_value's in the method) succeed else fail(diff) end else succeed end end |
#be_same_value_as(expected = nil) ⇒ Object
276 277 278 |
# File 'lib/assert_value.rb', line 276 def be_same_value_as(expected = nil) BeSameValueAs.new(expected) end |
#file_offsets ⇒ Object
83 84 85 |
# File 'lib/assert_value.rb', line 83 def file_offsets @@file_offsets ||= Hash.new { |hash, key| hash[key] = {} } end |