Skip to content

Commit 874e034

Browse files
committed
Change output format of failed #expect_raises in specs
1 parent c3d14e6 commit 874e034

File tree

2 files changed

+150
-16
lines changed

2 files changed

+150
-16
lines changed

spec/std/spec/expectations_spec.cr

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,99 @@ describe "expectations" do
172172
it "pass if raises MyError" do
173173
expect_raises(Exception, "Ops") { raise Exception.new("Ops") }
174174
end
175+
176+
describe "failure message format" do
177+
context "given string to compare with message" do
178+
it "contains expected exception, actual exception and backtrace" do
179+
expect_raises(Exception, "digits should be non-negative") do
180+
raise IndexError.new("Index out of bounds")
181+
end
182+
rescue e : Spec::AssertionFailed
183+
e.message.as(String).should contain(<<-MESSAGE)
184+
Expected Exception with message containing: "digits should be non-negative"
185+
got IndexError with message: "Index out of bounds"
186+
Backtrace:
187+
# spec/std/spec/expectations_spec.cr:#{__LINE__ - 7}:13 in '->'
188+
MESSAGE
189+
else
190+
raise "nothing is raised"
191+
end
192+
193+
it "contains expected class, actual exception and backtrace when expected class does not match actial class" do
194+
expect_raises(ArgumentError, "digits should be non-negative") do
195+
raise IndexError.new("Index out of bounds")
196+
end
197+
rescue e : Spec::AssertionFailed
198+
e.message.as(String).should contain(<<-MESSAGE)
199+
Expected ArgumentError
200+
got IndexError with message: "Index out of bounds"
201+
Backtrace:
202+
# spec/std/spec/expectations_spec.cr:#{__LINE__ - 7}:13 in '->'
203+
MESSAGE
204+
else
205+
raise "nothing is raised"
206+
end
207+
208+
it "escapes expected and actual messages in the same way" do
209+
expect_raises(Exception, %q(a\tb\nc)) do
210+
raise %q(a\tb\nc).inspect
211+
end
212+
rescue e : Spec::AssertionFailed
213+
e.message.as(String).should contain("Expected Exception with message containing: #{%q(a\tb\nc).inspect}")
214+
e.message.as(String).should contain("got Exception with message: #{%q(a\tb\nc).inspect.inspect}")
215+
else
216+
raise "nothing is raised"
217+
end
218+
end
219+
220+
context "given regex to match a message" do
221+
it "contains expected exception, actual exception and backtrace" do
222+
expect_raises(Exception, /digits should be non-negative/) do
223+
raise IndexError.new("Index out of bounds")
224+
end
225+
rescue e : Spec::AssertionFailed
226+
e.message.as(String).should contain(<<-MESSAGE)
227+
Expected Exception with message matching: /digits should be non-negative/
228+
got IndexError with message: "Index out of bounds"
229+
Backtrace:
230+
# spec/std/spec/expectations_spec.cr:#{__LINE__ - 7}:13 in '->'
231+
MESSAGE
232+
else
233+
raise "nothing is raised"
234+
end
235+
236+
it "contains expected class, actual exception and backtrace when expected class does not match actial class" do
237+
expect_raises(ArgumentError, /digits should be non-negative/) do
238+
raise IndexError.new("Index out of bounds")
239+
end
240+
rescue e : Spec::AssertionFailed
241+
e.message.as(String).should contain(<<-MESSAGE)
242+
Expected ArgumentError
243+
got IndexError with message: "Index out of bounds"
244+
Backtrace:
245+
# spec/std/spec/expectations_spec.cr:#{__LINE__ - 7}:13 in '->'
246+
MESSAGE
247+
else
248+
raise "nothing is raised"
249+
end
250+
end
251+
252+
context "given nil to allow any message" do
253+
it "contains expected class, actual exception and backtrace when expected class does not match actial class" do
254+
expect_raises(ArgumentError, nil) do
255+
raise IndexError.new("Index out of bounds")
256+
end
257+
rescue e : Spec::AssertionFailed
258+
e.message.as(String).should contain(<<-MESSAGE)
259+
Expected ArgumentError
260+
got IndexError with message: "Index out of bounds"
261+
Backtrace:
262+
# spec/std/spec/expectations_spec.cr:#{__LINE__ - 7}:13 in '->'
263+
MESSAGE
264+
else
265+
raise "nothing is raised"
266+
end
267+
end
268+
end
175269
end
176270
end

src/spec/expectations.cr

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -410,32 +410,72 @@ module Spec
410410
raise ex
411411
end
412412

413-
ex_to_s = ex.to_s
414-
case message
415-
when Regex
416-
unless (ex_to_s =~ message)
417-
backtrace = ex.backtrace.join('\n') { |f| " # #{f}" }
418-
fail "Expected #{klass} with message matching #{message.pretty_inspect}, " \
419-
"got #<#{ex.class}: #{ex_to_s}> with backtrace:\n#{backtrace}", file, line
413+
case {ex.message, message}
414+
when {String, Regex}
415+
unless ex.message =~ message
416+
expectation_failed_message = build_expectation_failed_message(klass, message, ex)
417+
fail expectation_failed_message, file, line
420418
end
421-
when String
422-
unless ex_to_s.includes?(message)
423-
backtrace = ex.backtrace.join('\n') { |f| " # #{f}" }
424-
fail "Expected #{klass} with #{message.pretty_inspect}, got #<#{ex.class}: " \
425-
"#{ex_to_s}> with backtrace:\n#{backtrace}", file, line
419+
when {String, String}
420+
unless ex.message == message
421+
expectation_failed_message = build_expectation_failed_message(klass, message, ex)
422+
fail expectation_failed_message, file, line
426423
end
427-
when Nil
424+
when {_, Nil}
428425
# No need to check the message
429426
end
430427

431428
ex
432429
rescue ex
433-
backtrace = ex.backtrace.join('\n') { |f| " # #{f}" }
434-
fail "Expected #{klass}, got #<#{ex.class}: #{ex}> with backtrace:\n" \
435-
"#{backtrace}", file, line
430+
expectation_failed_message = build_expectation_failed_message(klass, ex)
431+
fail expectation_failed_message, file, line
436432
else
437433
fail "Expected #{klass} but nothing was raised", file, line
438434
end
435+
436+
private def build_expectation_failed_message(klass : Class, message : String, exception : Exception)
437+
backtrace = exception.backtrace.join('\n') { |f| " # #{f}" }
438+
439+
<<-MESSAGE
440+
Expected #{klass} with message containing: #{message.inspect}
441+
got #{exception.class} with message: #{exception.message.inspect}
442+
Backtrace:
443+
#{backtrace}
444+
MESSAGE
445+
end
446+
447+
private def build_expectation_failed_message(klass : Class, message : Regex, exception : Exception)
448+
backtrace = exception.backtrace.join('\n') { |f| " # #{f}" }
449+
450+
<<-MESSAGE
451+
Expected #{klass} with message matching: #{message.inspect}
452+
got #{exception.class} with message: #{exception.message.inspect}
453+
Backtrace:
454+
#{backtrace}
455+
MESSAGE
456+
end
457+
458+
private def build_expectation_failed_message(klass : Class, message : Nil, exception : Exception)
459+
backtrace = exception.backtrace.join('\n') { |f| " # #{f}" }
460+
461+
<<-MESSAGE
462+
Expected #{klass} with any message
463+
got #{exception.class} with message: #{exception.message.inspect}
464+
Backtrace:
465+
#{backtrace}
466+
MESSAGE
467+
end
468+
469+
private def build_expectation_failed_message(klass : Class, exception : Exception)
470+
backtrace = exception.backtrace.join('\n') { |f| " # #{f}" }
471+
472+
<<-MESSAGE
473+
Expected #{klass}
474+
got #{exception.class} with message: #{exception.message.inspect}
475+
Backtrace:
476+
#{backtrace}
477+
MESSAGE
478+
end
439479
{% end %}
440480
end
441481

0 commit comments

Comments
 (0)