Skip to content

Commit 9137639

Browse files
committed
Better error handling + failure messages
Signed-off-by: Samuel Giddins <segiddins@segiddins.me>
1 parent 722c89c commit 9137639

File tree

12 files changed

+129
-47
lines changed

12 files changed

+129
-47
lines changed

lib/quickdraw/configuration.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ def initialize
88
@registry = Quickdraw::Registry.new
99
@failure_symbol = "\e[31m⨯\e[0m"
1010
@success_symbol = "\e[32m∘\e[0m"
11+
@error_symbol = "\e[31me\e[0m"
1112
@processes = DEFAULT_PROCESSES
1213
@threads = DEFAULT_THREADS
1314
@success_emoji = %w[💃 🕺 🎉 🎊 💪 👏 🙌 🥳 🎈 🌈 🎯 🏆]
@@ -20,6 +21,7 @@ def initialize
2021
attr_accessor :success_emoji
2122
attr_accessor :success_symbol
2223
attr_accessor :threads
24+
attr_accessor :error_symbol
2325

2426
def matcher(matcher, *types)
2527
@registry.register(matcher, *types)

lib/quickdraw/context.rb

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ def run_test(name, skip, runner, &)
3434
instance = new(name, skip, runner, matchers)
3535
instance.instance_exec(&)
3636
instance.resolve
37+
rescue Exception => error
38+
runner.error!(name, error)
3739
end
3840
end
3941

@@ -74,37 +76,37 @@ def resolve
7476

7577
def assert(value)
7678
if value
77-
success!
79+
success!(depth: 1)
7880
elsif block_given?
79-
failure! { yield(value) }
81+
failure!(depth: 1) { yield(value) }
8082
else
81-
failure! { "expected #{value.inspect} to be truthy" }
83+
failure!(depth: 1) { "expected #{value.inspect} to be truthy" }
8284
end
8385
end
8486

8587
def refute(value)
8688
if !value
87-
success!
89+
success!(depth: 1)
8890
elsif block_given?
89-
failure! { yield(value) }
91+
failure!(depth: 1) { yield(value) }
9092
else
91-
failure! { "expected #{value.inspect} to be falsy" }
93+
failure!(depth: 1) { "expected #{value.inspect} to be falsy" }
9294
end
9395
end
9496

95-
def success!
97+
def success!(depth:)
9698
if @skip
97-
@runner.failure! { "The skipped test `#{@name}` started passing." }
99+
@runner.failure!(@name, depth:) { "The skipped test `#{@name}` started passing." }
98100
else
99-
@runner.success!(@name)
101+
@runner.success!(@name, depth:)
100102
end
101103
end
102104

103-
def failure!(&)
105+
def failure!(depth:, &)
104106
if @skip
105-
@runner.success!(@name)
107+
@runner.success!(@name, depth:)
106108
else
107-
@runner.failure!(&)
109+
@runner.failure!(@name, depth:, &)
108110
end
109111
end
110112
end

lib/quickdraw/expectation.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,29 +37,29 @@ def initialize(context, subject = Quickdraw::Null, &block)
3737
@made_expectations = false
3838
end
3939

40-
def success!
41-
@context.success!
40+
def success!(depth:)
41+
@context.success!(depth: depth)
4242
@made_expectations = true
4343
end
4444

45-
def failure!(&)
46-
@context.failure!(&)
45+
def failure!(depth:, &)
46+
@context.failure!(depth:, &)
4747
@made_expectations = true
4848
end
4949

5050
def resolve
5151
unless @made_expectations
52-
failure! { "You didn't make any expectations." }
52+
failure!(depth: 2) { "You didn't make any expectations." }
5353
end
5454
end
5555

5656
private
5757

58-
def assert(value, &)
59-
value ? success! : failure!(&)
58+
def assert(value, depth: 1, &)
59+
value ? success!(depth:) : failure!(depth:, &)
6060
end
6161

62-
def refute(value, &)
63-
value ? failure!(&) : success!
62+
def refute(value, depth: 1, &)
63+
value ? failure!(depth:, &) : success!(depth:)
6464
end
6565
end

lib/quickdraw/matchers/to_have_attributes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ def to_have_attributes(**attributes)
88
end
99
end
1010
rescue NoMethodError => e
11-
failure! { "expected `#{@subject.inspect}` to respond to `#{e.name}`" }
11+
failure!(depth: 1) { "expected `#{@subject.inspect}` to respond to `#{e.name}`" }
1212
end
1313
end

lib/quickdraw/matchers/to_raise.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ def to_raise(error = ::Exception)
77
begin
88
expectation_block.call
99
rescue error => e
10-
success!
10+
success!(depth: 1)
1111
yield(e) if block_given?
1212
return
1313
rescue ::Exception => e
14-
return failure! { "expected `#{error.inspect}` to be raised but `#{e.class.inspect}` was raised" }
14+
return failure!(depth: 1) { "expected `#{error.inspect}` to be raised but `#{e.class.inspect}` was raised" }
1515
end
1616

17-
failure! { "expected #{error} to be raised but wasn't" }
17+
failure!(depth: 1) { "expected #{error} to be raised but wasn't" }
1818
end
1919

2020
def not_to_raise
2121
@block.call
22-
success!
22+
success!(depth: 1)
2323
rescue ::Exception => e
24-
failure! { "expected the block not to raise, but it raised `#{e.class}`" }
24+
failure!(depth: 1) { "expected the block not to raise, but it raised `#{e.class}`" }
2525
end
2626
end

lib/quickdraw/matchers/to_receive.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def to_receive(method_name, &expectation_block)
99
context = @context
1010

1111
interceptor.define_method(method_name) do |*args, **kwargs, &block|
12-
expectation.success!
12+
expectation.success!(depth: 2)
1313
super_block = -> (*a, &b) { ((a.length > 0) || b) ? super(*a, &b) : super(*args, **kwargs, &block) }
1414
original_super = context.instance_variable_get(:@super)
1515
begin

lib/quickdraw/run.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,27 @@ def call
3131

3232
results.each do |r|
3333
failures = r["failures"]
34+
errors = r["errors"]
3435

3536
i = 0
3637
number_of_failures = failures.size
3738
total_failures += number_of_failures
3839
while i < number_of_failures
3940
failure = failures[i]
40-
path, lineno, message = failure
41-
puts "#{path}:#{lineno} #{message}"
41+
test_name, path, lineno, message = failure
42+
puts "#{path}:#{lineno} in #{test_name.inspect}: #{message}"
4243
i += 1
4344
end
45+
46+
number_of_errors = errors.size
47+
total_failures += number_of_errors
48+
while i < number_of_errors
49+
error = errors[i]
50+
test_name, cls, message, backtrace = error
51+
puts "Unexpected #{cls} in #{test_name}:\n#{message}\n#{backtrace.join("\n\t")}"
52+
i += 1
53+
end
54+
4455
end
4556

4657
puts "Ran with seed: #{@seed}"

lib/quickdraw/runner.rb

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def initialize(queue:, threads:)
99

1010
@failures = Concurrent::Array.new
1111
@successes = Concurrent::Array.new
12+
@errors = Concurrent::Array.new
1213
end
1314

1415
def call
@@ -24,26 +25,35 @@ def call
2425
"pid" => Process.pid,
2526
"failures" => @failures.to_a,
2627
"successes" => @successes.size,
28+
"errors" => @errors.to_a,
2729
}
2830
end
2931

30-
def success!(name)
32+
def success!(name, depth: 0)
3133
@successes << name
3234

3335
Kernel.print(
3436
Quickdraw::Config.success_symbol,
3537
)
3638
end
3739

38-
def failure!
39-
location = caller_locations(3, 1).first
40-
@failures << [location.path, location.lineno, yield]
40+
def failure!(name, depth: 0)
41+
location = caller_locations(2 + depth, 1).first
42+
@failures << [name, location.path, location.lineno, yield]
4143

4244
Kernel.print(
4345
Quickdraw::Config.failure_symbol,
4446
)
4547
end
4648

49+
def error!(name, error)
50+
@errors << [name, error.class.name, error.detailed_message, error.backtrace]
51+
52+
Kernel.print(
53+
Quickdraw::Config.error_symbol,
54+
)
55+
end
56+
4757
private
4858

4959
def drain_queue

test/assert.test.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
test "assert with falsy value" do
1212
expect {
1313
test { assert false }
14-
}.to_fail message: "expected false to be truthy"
14+
}.to_fail message: "expected false to be truthy", location: [__FILE__, __LINE__ - 1]
1515
end
1616

1717
test "assert with truthy value" do
@@ -23,5 +23,11 @@
2323
test "assert with custom failure message" do
2424
expect {
2525
test { assert(false) { "Message" } }
26-
}.to_fail message: "Message"
26+
}.to_fail message: "Message", location: [__FILE__, __LINE__ - 1]
27+
end
28+
29+
test "assert with custom message raising an error" do
30+
expect {
31+
test { assert(false) { raise ArgumentError } }
32+
}.to_error
2733
end

test/matchers/pattern_match.test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
test "when not equal" do
1010
expect {
1111
test { expect("a") =~ /b/ }
12-
}.to_fail message: %(expected `"a"` to =~ `"/b/"`)
12+
}.to_fail message: %(expected `"a"` to =~ `/b/`)
1313
end

0 commit comments

Comments
 (0)