wrong 0.4.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/README.markdown +300 -0
  2. data/lib/wrong.rb +27 -0
  3. data/lib/wrong/adapters/minitest.rb +14 -0
  4. data/lib/wrong/adapters/rspec.rb +21 -0
  5. data/lib/wrong/adapters/test_unit.rb +9 -0
  6. data/lib/wrong/assert.rb +105 -0
  7. data/lib/wrong/chunk.rb +233 -0
  8. data/lib/wrong/close_to.rb +9 -0
  9. data/lib/wrong/config.rb +29 -0
  10. data/lib/wrong/d.rb +42 -0
  11. data/lib/wrong/failure_message.rb +43 -0
  12. data/lib/wrong/helpers.rb +66 -0
  13. data/lib/wrong/irb.rb +16 -0
  14. data/lib/wrong/message/array_diff.rb +69 -0
  15. data/lib/wrong/message/string_comparison.rb +88 -0
  16. data/lib/wrong/message/test_context.rb +28 -0
  17. data/lib/wrong/rainbow.rb +127 -0
  18. data/lib/wrong/ruby2ruby_patch.rb +37 -0
  19. data/lib/wrong/sexp_ext.rb +49 -0
  20. data/lib/wrong/version.rb +3 -0
  21. data/test/adapters/minitest_test.rb +97 -0
  22. data/test/adapters/rspec1/failing_spec.rb +23 -0
  23. data/test/adapters/rspec2/failing_spec.rb +26 -0
  24. data/test/adapters/rspec_test.rb +104 -0
  25. data/test/adapters/test_unit_test.rb +59 -0
  26. data/test/assert_advanced_test.rb +51 -0
  27. data/test/assert_test.rb +76 -0
  28. data/test/capturing_test.rb +59 -0
  29. data/test/chunk_test.rb +264 -0
  30. data/test/close_to_test.rb +39 -0
  31. data/test/config_test.rb +89 -0
  32. data/test/d_test.rb +64 -0
  33. data/test/failure_message_test.rb +40 -0
  34. data/test/failures_test.rb +157 -0
  35. data/test/message/array_diff_test.rb +79 -0
  36. data/test/message/test_context_test.rb +69 -0
  37. data/test/rescuing_test.rb +17 -0
  38. data/test/separate.rb +4 -0
  39. data/test/sexp_ext_test.rb +80 -0
  40. data/test/string_comparison_test.rb +159 -0
  41. data/test/suite.rb +7 -0
  42. data/test/test_helper.rb +64 -0
  43. data/test/wrong_test.rb +60 -0
  44. metadata +215 -0
@@ -0,0 +1,23 @@
1
+ # This is a failing spec for testing RSpec 1.3 integration
2
+
3
+ require "rubygems"
4
+ require "bundler"
5
+ Bundler.setup
6
+
7
+ require "spec"
8
+
9
+ here = File.expand_path(File.dirname(__FILE__))
10
+ $:.unshift "#{here}/../../../lib"
11
+ require "wrong/adapters/rspec"
12
+
13
+ # since we're not running 'spec' we have to do some stuff ourselves
14
+ include Spec::DSL::Main
15
+
16
+ describe "arithmetic" do
17
+ it "should not work like this" do
18
+ assert { 2 + 2 == 5 }
19
+ end
20
+ end
21
+
22
+ Spec::Runner.options.parse_format("nested")
23
+ Spec::Runner.options.run_examples
@@ -0,0 +1,26 @@
1
+ # This is a failing spec for testing RSpec 2 integration
2
+
3
+ require "rubygems"
4
+ require "bundler"
5
+ Bundler.setup
6
+
7
+ require "rspec"
8
+
9
+ here = File.expand_path(File.dirname(__FILE__))
10
+ $:.unshift "#{here}/../../../lib"
11
+
12
+ # since we're not running 'rspec' we have to do some stuff ourselves
13
+ require 'rspec'
14
+ require 'rspec/core'
15
+ puts RSpec::Core::Version::STRING
16
+
17
+ require 'rspec/autorun'
18
+ require "wrong/adapters/rspec"
19
+
20
+ describe "arithmetic" do
21
+ it "should not work like this" do
22
+ assert { 2 + 2 == 5 }
23
+ end
24
+ end
25
+
26
+ # now, thanks to the require 'rspec/autorun', this spec will run and fail
@@ -0,0 +1,104 @@
1
+ here = File.expand_path(File.dirname(__FILE__))
2
+
3
+ require "open3"
4
+ require "fileutils"
5
+
6
+ require "./test/test_helper"
7
+ require "wrong/adapters/minitest"
8
+
9
+ include Wrong
10
+
11
+ # Okay, this looks like RSpec but it's actually minitest
12
+ describe "testing rspec" do
13
+
14
+ def sys(cmd, expected_status = 0)
15
+ start_time = Time.now
16
+ $stderr.print cmd
17
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thread|
18
+ # in Ruby 1.8, wait_thread is nil :-( so just pretend the process was successful (status 0)
19
+ exit_status = (wait_thread.value.exitstatus if wait_thread) || 0
20
+ output = stdout.read + stderr.read
21
+ unless expected_status.nil?
22
+ assert { output and exit_status == expected_status }
23
+ end
24
+ yield output if block_given?
25
+ output
26
+ end
27
+ ensure
28
+ $stderr.puts " (#{"%.2f" % (Time.now - start_time)} sec)"
29
+ end
30
+
31
+ def clear_bundler_env
32
+ # Bundler inherits its environment by default, so clear it here
33
+ %w{BUNDLE_PATH BUNDLE_BIN_PATH BUNDLE_GEMFILE}.each { |var| ENV.delete(var) }
34
+ end
35
+
36
+ [1, 2].each do |rspec_version|
37
+ it "version #{rspec_version}" do
38
+ dir = "#{here}/rspec#{rspec_version}"
39
+ spec_output = nil
40
+ Dir.chdir(dir) do
41
+ clear_bundler_env
42
+ FileUtils.rm "#{dir}/Gemfile.lock", :force => true
43
+
44
+ sys "bundle check" do |output|
45
+ unless output == "The Gemfile's dependencies are satisfied\n"
46
+ sys "bundle install --gemfile=#{dir}/Gemfile --local"
47
+ end
48
+ end
49
+
50
+ sys "bundle list" do |output|
51
+ lines = output.split("\n")
52
+ lines.grep(/rspec/) do |line|
53
+ assert { line =~ /rspec[-\w]* \(#{rspec_version}\.[\w.]*\)/ }
54
+ end
55
+ end
56
+
57
+ spec_output = sys "ruby #{dir}/failing_spec.rb",
58
+ (rspec_version == 1 || RUBY_VERSION =~ /^1\.8\./ || RUBY_VERSION == '1.9.1' ? nil : 1) # RSpec v1 exits with 0 on failure :-(
59
+ end
60
+
61
+ assert { spec_output.include? "1 example, 1 failure" }
62
+ assert { spec_output.include? "Expected ((2 + 2) == 5), but" }
63
+ end
64
+ end
65
+ end
66
+
67
+ =begin
68
+ # I would use
69
+ # out, err = capturing(:stdout, :stderr) do
70
+ # but minitest does its own arcane stream munging and it's not working
71
+
72
+ out = StringIO.new
73
+ err = StringIO.new
74
+ Spec::Runner.use(Spec::Runner::Options.new(out, err))
75
+
76
+ module RSpecWrapper
77
+ include Spec::DSL::Main
78
+ describe "inside rspec land" do
79
+ it "works" do
80
+ sky = "blue"
81
+ assert { sky == "green" }
82
+ end
83
+ end
84
+ end
85
+
86
+ Spec::Runner.options.parse_format("nested")
87
+ Spec::Runner.options.run_examples
88
+
89
+ assert(err.string.index(<<-RSPEC) == 0, "make sure the rspec formatter was used")
90
+ inside rspec land
91
+ works (FAILED - 1)
92
+
93
+ 1)
94
+ 'inside rspec land works' FAILED
95
+ RSPEC
96
+
97
+ failures = Spec::Runner.options.reporter.instance_variable_get(:@failures) # todo: use my own reporter?
98
+ assert !failures.empty?
99
+ exception = failures.first.exception
100
+ assert(exception.is_a?(Spec::Expectations::ExpectationNotMetError))
101
+ assert(exception.message =~ /^Expected \(sky == \"green\"\), but/, "message is #{exception.message.inspect}")
102
+ end
103
+ end
104
+ =end
@@ -0,0 +1,59 @@
1
+ require "./test/test_helper"
2
+
3
+ require "test/unit"
4
+
5
+ #require "wrong/assert"
6
+ require "wrong/adapters/test_unit"
7
+
8
+ # get rid of atrocious Test::Unit color scheme (gray on green = puke)
9
+ Test::Unit::AutoRunner.setup_option do |auto_runner, opts|
10
+ auto_runner.runner_options[:use_color] = false
11
+ end
12
+
13
+ class MyFailingAssertTest < Test::Unit::TestCase
14
+
15
+ def test_wrong_assert_and_deny_are_available_to_test_unit_tests
16
+ my_failing_assert_test = Class.new(Test::Unit::TestCase)
17
+ my_failing_assert_test.class_eval do
18
+ def test_fail
19
+ assert{1==2}
20
+ end
21
+ end
22
+
23
+ my_failing_deny_test = Class.new(Test::Unit::TestCase)
24
+ my_failing_deny_test.class_eval do
25
+ def test_fail
26
+ deny{1==1}
27
+ end
28
+ end
29
+
30
+ result = Test::Unit::TestResult.new
31
+ my_failing_assert_test.new("test_fail").run(result) {|started, name| }
32
+ #I can do without all the TU Listener business, thank you
33
+ failures = result.instance_variable_get("@failures".to_sym)
34
+ assert{ failures.length==1 }
35
+ assert{ failures.first.long_display.include?("1 is not equal to 2") }
36
+
37
+ result = Test::Unit::TestResult.new
38
+ failures = result.instance_variable_get("@failures".to_sym)
39
+ my_failing_deny_test.new("test_fail").run(result) {|started, name| }
40
+ assert{ failures.length==1 }
41
+ assert{ failures.first.long_display.include?("1 is equal to 1") }
42
+ end
43
+
44
+ def test_passes_asserts_with_no_block_up_to_the_frameworks_assert_method
45
+ e = rescuing { assert(1 == 2) }
46
+ assert { e.message == "<false> is not true." }
47
+
48
+ e = rescuing { assert(1 == 2, "black is white") }
49
+ assert { e.message == "black is white.\n<false> is not true." }
50
+ end
51
+
52
+ def test_passes_denys_with_no_block_up_to_the_frameworks_assert_method
53
+ e = rescuing { deny(2 + 2 == 4) }
54
+ assert { e.message == "<false> is not true." }
55
+
56
+ e = rescuing { deny(2 + 2 == 4, "up is down") }
57
+ assert { e.message == "up is down.\n<false> is not true." }
58
+ end
59
+ end
@@ -0,0 +1,51 @@
1
+ require "./test/test_helper"
2
+ require "wrong/assert"
3
+ require "wrong/adapters/minitest"
4
+
5
+ describe "advanced assert features" do
6
+
7
+ def assert_later(&p)
8
+ assert(&p)
9
+ end
10
+
11
+ # dunno why, but this fails under JRuby (both 1.8 and 1.9)
12
+ unless Object.const_defined? :JRuby
13
+ it "is possible (but hardly advisable) to define procs in different places from the assert call" do
14
+ x = 10
15
+ e = get_error do
16
+ assert_later { x > 10 }
17
+ end
18
+
19
+ assert(e.message =~ /Expected \(x > 10\), but.*x is 10/m, e.message)
20
+ end
21
+ end
22
+
23
+ xit "can parse a here doc defined inside the block" do
24
+ # todo: test in Chunk too
25
+ assert { "123\n456" == <<-TEXT
26
+ 123
27
+ 456
28
+ TEXT
29
+ }
30
+ end
31
+
32
+ xit "can parse a here doc defined outside the block" do
33
+ # todo: test in Chunk too
34
+ assert { "123\n456" == <<-TEXT }
35
+ 123
36
+ 456
37
+ TEXT
38
+ end
39
+
40
+ it "finds the file to parse even when inside a chdir to a child directory" do
41
+ e = get_error do
42
+ Dir.chdir("test") do
43
+ assert { (1 + 2) == 5 }
44
+ end
45
+ end
46
+ assert { e.message.include? "Expected ((1 + 2) == 5), but" }
47
+ end
48
+
49
+ # todo: test for finding it if you'd changed dirs into a parent or sibling or cousin dir
50
+
51
+ end
@@ -0,0 +1,76 @@
1
+ require "./test/test_helper"
2
+ require "wrong/assert"
3
+
4
+ describe "basic assert features" do
5
+
6
+ before do
7
+ @m = Module.new do
8
+ extend Wrong::Assert
9
+ end
10
+ end
11
+
12
+ describe "pass/fail basics" do
13
+ it "passes when the result is true. deny does the reverse" do
14
+ @m.assert { true }
15
+ @m.assert { 1==1 }
16
+
17
+ @m.deny { false }
18
+ @m.deny { 1==2 }
19
+ end
20
+
21
+ it "fails when result is false. deny does the reverse" do
22
+ get_error {
23
+ @m.assert { false }
24
+ } || fail
25
+ get_error {
26
+ @m.assert { 1==2 }
27
+ } || fail
28
+
29
+ get_error {
30
+ @m.deny { true }
31
+ } || fail
32
+ get_error {
33
+ @m.deny { 1==1 }
34
+ } || fail
35
+ end
36
+
37
+ class MyError < StandardError;
38
+ end
39
+
40
+ describe "assert" do
41
+ it "fails when an error is thrown and bubbles up the error" do
42
+ assert_raises(MyError) { @m.assert { raise MyError.new } }
43
+ end
44
+
45
+ it "takes an optional explanation" do
46
+ e = get_error {
47
+ sky = "green"
48
+ @m.assert("the sky should be blue") { sky == "blue" }
49
+ }
50
+ assert e.message =~ /^the sky should be blue: /, e.message
51
+ end
52
+
53
+ it "gives a meaningful error when passed no block" do
54
+ e = get_error {
55
+ @m.assert(2+2 == 5)
56
+ }
57
+ assert e.message =~ /a block/, e.message
58
+ end
59
+ end
60
+
61
+ describe "deny" do
62
+ it "fails when an error is thrown and bubbles up the error" do
63
+ assert_raises(MyError) { @m.deny { raise MyError.new } }
64
+ end
65
+
66
+ it "takes an optional explanation" do
67
+ e = get_error {
68
+ sky = "blue"
69
+ @m.deny("the sky should not be blue") { sky == "blue" }
70
+ }
71
+ assert e.message =~ /^the sky should not be blue: /,
72
+ e.message + "\n\t" + e.backtrace.join("\n\t")
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,59 @@
1
+ require "./test/test_helper"
2
+
3
+ require "wrong/assert"
4
+ require "wrong/helpers"
5
+
6
+ describe "a tool for capturing output" do
7
+
8
+ include Wrong::Assert
9
+ include Wrong::Helpers
10
+
11
+ it "captures stdout" do
12
+ assert {
13
+ capturing { puts "hi" } == "hi\n"
14
+ }
15
+ end
16
+
17
+ it "captures stderr" do
18
+ assert {
19
+ capturing(:stderr) { $stderr.puts "hi" } == "hi\n"
20
+ }
21
+ end
22
+
23
+ it "captures both" do
24
+ out, err = capturing(:stdout, :stderr) do
25
+ $stdout.puts "hi"
26
+ $stderr.puts "bye"
27
+ end
28
+
29
+ assert { out == "hi\n"}
30
+ assert { err == "bye\n"}
31
+
32
+ end
33
+
34
+ it "supports nesting" do
35
+ inside = nil
36
+ outside = capturing do
37
+ puts "bread"
38
+ inside = capturing do
39
+ puts "ham"
40
+ end
41
+ puts "more bread"
42
+ end
43
+
44
+ assert { inside == "ham\n"}
45
+ assert { outside == "bread\nham\nmore bread\n"}
46
+ end
47
+
48
+
49
+ it "bails if stream was reassigned" do
50
+ e = rescuing do
51
+ capturing do
52
+ $stdout = StringIO.new # uh-oh!
53
+ end
54
+ end
55
+ assert { e.message =~ /^stdout was reassigned/ }
56
+ end
57
+
58
+
59
+ end
@@ -0,0 +1,264 @@
1
+ require "./test/test_helper"
2
+ require "wrong/chunk"
3
+
4
+ unless Object.const_defined?(:Chunk)
5
+ Chunk = Wrong::Chunk
6
+ end
7
+
8
+ describe Chunk do
9
+ describe "#from_block" do
10
+ it "reads the source location" do
11
+ file, line = __FILE__, __LINE__
12
+ chunk = Chunk.from_block(proc { "hi" })
13
+ assert(chunk.file == file)
14
+ assert(chunk.line_number == line+1)
15
+ end
16
+ end
17
+
18
+ describe "line numbers" do
19
+ before do
20
+ @chunk = Wrong::Chunk.new("foo.rb", 10)
21
+ end
22
+ it "#line_index is zero-based" do
23
+ assert(@chunk.line_index == 9)
24
+ end
25
+ it "#location is one-based" do
26
+ assert(@chunk.location == "foo.rb:10")
27
+ end
28
+ end
29
+
30
+ describe "parsing" do
31
+ it "reads a statement on a line by itself" do
32
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
33
+ "hi"
34
+ CODE
35
+ code = chunk.sexp.to_ruby
36
+ assert(code == '"hi"')
37
+ end
38
+
39
+ it "reads a statement on multiple lines" do
40
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
41
+ proc do
42
+ "hi"
43
+ end
44
+ CODE
45
+ code = chunk.sexp.to_ruby
46
+ assert(code == "proc { \"hi\" }")
47
+ end
48
+
49
+ it "fails if there's a stray close-paren symbol on the last line (sorry)" do
50
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
51
+ "hi" )
52
+ CODE
53
+ assert(chunk.sexp.nil?)
54
+ end
55
+
56
+ it "fails if there's a stray close-block symbol on the last line (sorry)" do
57
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
58
+ "hi" }
59
+ CODE
60
+ assert(chunk.sexp.nil?)
61
+ end
62
+
63
+ it "fails if it can't parse the code" do
64
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
65
+ }
66
+ CODE
67
+ assert(chunk.sexp.nil?)
68
+ end
69
+
70
+ it "fails if it can't find the file" do
71
+ chunk = Chunk.new("nonexistent_file.rb", 0)
72
+ error = get_error { chunk.sexp }
73
+ assert error.is_a? Errno::ENOENT
74
+ end
75
+
76
+ it "finds the file to parse even when inside a chdir to a child directory" do
77
+ Dir.chdir("test") do
78
+ chunk = Chunk.new __FILE__, __LINE__ + 1; <<-CODE
79
+ "hi"
80
+ CODE
81
+ code = chunk.sexp.to_ruby
82
+ assert(code == '"hi"')
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "#claim" do
88
+ it "returns the part of the assertion statement inside the curly braces" do
89
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
90
+ assert { x == 5 }
91
+ CODE
92
+ full_code = chunk.sexp.to_ruby
93
+ assert(full_code == "assert { (x == 5) }")
94
+ claim_code = chunk.claim.to_ruby
95
+ assert claim_code == "(x == 5)"
96
+ end
97
+
98
+
99
+ it "reads an assert statement on a line by itself" do
100
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
101
+ assert { x == 5 }
102
+ CODE
103
+ claim_code = chunk.claim.to_ruby
104
+ assert claim_code == "(x == 5)"
105
+ end
106
+
107
+ it "reads an assert statement on multiple lines" do
108
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
109
+ assert do
110
+ x == 5
111
+ end
112
+ CODE
113
+ claim_code = chunk.claim.to_ruby
114
+ assert claim_code == "(x == 5)"
115
+ end
116
+
117
+ def yielding
118
+ yield
119
+ end
120
+
121
+ if RUBY_VERSION > "1.9"
122
+ it "reads an assert statement that's nested inside another yield block on the same line (Ruby 1.9 only)" do
123
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
124
+ yielding { assert { x == 5 }}
125
+ CODE
126
+ code = chunk.claim.to_ruby
127
+ assert code == "(x == 5)"
128
+ end
129
+
130
+ # test "goes crazy if you try to nest two asserts on the same line"
131
+ end
132
+
133
+ it "if it can't find an assertion, it uses the whole chunk" do
134
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
135
+ yielding { x == 5 }
136
+ CODE
137
+ code = chunk.claim.to_ruby
138
+ assert code == "yielding { (x == 5) }"
139
+ end
140
+
141
+ it "fails if it can't parse the code" do
142
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
143
+ }
144
+ CODE
145
+ error = get_error {
146
+ chunk.claim
147
+ }
148
+ assert error.message.include?("Could not parse")
149
+ end
150
+ end
151
+
152
+ describe "#parts" do
153
+ it "returns all unique sub-expressions of the main sexpression" do
154
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
155
+ assert { (x == 5) && (y == (z + 10)) }
156
+ CODE
157
+ code_parts = chunk.parts
158
+ assert code_parts == <<-PARTS.split("\n")
159
+ ((x == 5) and (y == (z + 10)))
160
+ (x == 5)
161
+ x
162
+ 5
163
+ (y == (z + 10))
164
+ y
165
+ (z + 10)
166
+ z
167
+ 10
168
+ PARTS
169
+ end
170
+
171
+ it "omits the method-call-sans-block part of a method call with a block" do
172
+ chunk = Chunk.new(__FILE__, __LINE__ + 1); <<-CODE
173
+ assert { rescuing { 1 + 2 } }
174
+ CODE
175
+ code_parts = chunk.parts
176
+ assert !code_parts.include?("rescuing")
177
+ end
178
+ end
179
+
180
+ describe "#details" do
181
+ def details(&block)
182
+ chunk = Chunk.from_block(block, 1)
183
+ d = chunk.details
184
+ # puts d
185
+ d
186
+ end
187
+
188
+ it "returns an empty string if there are no parts" do
189
+ d = details { assert { true } }
190
+ assert d == ""
191
+ end
192
+
193
+ it "returns an string beginning with a newline if there are parts" do
194
+ x = 10
195
+ d = details { assert { x == 10 } }
196
+ assert d == "\n x is 10\n"
197
+ end
198
+
199
+ it "skips literals" do
200
+ d = details { assert { 10 == 11 } }
201
+ assert d == ""
202
+ end
203
+
204
+ it "shows lots of details" do
205
+ x = 10
206
+ d = details { assert { (x * (x - 10)) == (x / (x + 10)) } }
207
+ assert d == <<-DETAILS
208
+
209
+ (x * (x - 10)) is 0
210
+ x is 10
211
+ (x - 10) is 0
212
+ (x / (x + 10)) is 0
213
+ (x + 10) is 20
214
+ DETAILS
215
+ end
216
+
217
+ it "skips duplicates" do
218
+ x = 10
219
+ d = details { assert { (x + 5) == 1 + (x + 5) } }
220
+ assert d == <<-DETAILS
221
+
222
+ (x + 5) is 15
223
+ x is 10
224
+ (1 + (x + 5)) is 16
225
+ DETAILS
226
+ end
227
+
228
+ it "shows exceptions" do
229
+ d = details { assert { (raise "hi") == 1 } }
230
+ assert d == "\n raise(\"hi\") raises RuntimeError: hi\n"
231
+ end
232
+
233
+ it "indents newlines inside the exception message" do
234
+ d = details { assert { (raise "hello\nsailor") == 1 } }
235
+ assert d == "\n raise(\"hello\\nsailor\") raises RuntimeError: hello\n sailor\n"
236
+ end
237
+
238
+ it "abridges exceptions with no message" do
239
+ d = details { assert { (raise Exception.new) == 1 } }
240
+ assert d == "\n raise(Exception.new) raises Exception\n" +
241
+ " Exception.new is #<Exception: Exception>\n"
242
+ end
243
+
244
+ it "inspects values" do
245
+ x = "flavor:\tvanilla"
246
+ d = details { assert { x == "flavor:\tchocolate" } }
247
+ # this means it's a literal slash plus t inside double quotes -- i.e. it shows the escaped (inspected) string
248
+ assert d == "\n" + ' x is "flavor:\tvanilla"' + "\n"
249
+ end
250
+
251
+ it "indents unescaped newlines inside the inspected value" do
252
+ weirdo = Object.new
253
+
254
+ def weirdo.inspect
255
+ "first\nsecond\nthird"
256
+ end
257
+
258
+ x = weirdo
259
+ d = details { assert { x == "foo" } }
260
+ assert d == "\n x is first\n second\n third\n"
261
+ end
262
+
263
+ end
264
+ end