Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 1022ca6

Browse files
committed
Add RSpec::Support.failure_notifier.
This is intended to support the new `aggregate_failures` feature discussed in rspec/rspec-expectations#733. I put the `failure_notifier` here so that rspec-mocks can use it as well -- that way, when we are aggregating failures, we can aggregate rspec-mocks failures as well.
1 parent ad75824 commit 1022ca6

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

lib/rspec/support.rb

+25
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,31 @@ def self.method_handle_for(object, method_name)
7373
end
7474
end
7575

76+
# A single thread local variable so we don't excessively pollute that namespace.
77+
def self.thread_local_data
78+
Thread.current[:__rspec] ||= {}
79+
end
80+
81+
def self.failure_notifier=(callable)
82+
thread_local_data[:failure_notifier] = callable
83+
end
84+
85+
def self.failure_notifier
86+
thread_local_data[:failure_notifier] ||= method(:raise)
87+
end
88+
89+
def self.notify_failure(failure)
90+
failure_notifier.call(failure)
91+
end
92+
93+
def self.with_failure_notifier(callable)
94+
orig_notifier = failure_notifier
95+
self.failure_notifier = callable
96+
yield
97+
ensure
98+
self.failure_notifier = orig_notifier
99+
end
100+
76101
# The Differ is only needed when a a spec fails with a diffable failure.
77102
# In the more common case of all specs passing or the only failures being
78103
# non-diffable, we can avoid the extra cost of loading the differ, diff-lcs,

spec/rspec/support_spec.rb

+63
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,68 @@ def method_missing(name, *args, &block)
117117
end
118118
end
119119
end
120+
121+
describe "failure notification" do
122+
before { @failure_notifier = RSpec::Support.failure_notifier }
123+
after { RSpec::Support.failure_notifier = @failure_notifier }
124+
let(:error) { NotImplementedError.new("some message") }
125+
let(:failures) { [] }
126+
let(:append_to_failures_array_notifier) { failures.method(:<<) }
127+
128+
def notify(failure)
129+
RSpec::Support.notify_failure(failure)
130+
end
131+
132+
def append_to_failures_array_instead_of_raising
133+
avoid_raising_errors.and change { failures }.from([]).to([error])
134+
end
135+
136+
def raise_instead_of_appending_to_failures_array
137+
raise_error(error).and avoid_changing { failures }
138+
end
139+
140+
it "defaults to raising the provided exception" do
141+
expect { notify(error) }.to raise_error(error)
142+
end
143+
144+
it "can be set to another callable" do
145+
RSpec::Support.failure_notifier = append_to_failures_array_notifier
146+
147+
expect {
148+
notify(error)
149+
}.to append_to_failures_array_instead_of_raising
150+
end
151+
152+
it "isolates notifier changes to the current thread" do
153+
RSpec::Support.failure_notifier = append_to_failures_array_notifier
154+
155+
Thread.new do
156+
expect { notify(error) }.to raise_instead_of_appending_to_failures_array
157+
end.join
158+
end
159+
160+
it "can be changed for the duration of a block" do
161+
yielded = false
162+
163+
RSpec::Support.with_failure_notifier(append_to_failures_array_notifier) do
164+
yielded = true
165+
expect {
166+
notify(error)
167+
}.to append_to_failures_array_instead_of_raising
168+
end
169+
170+
expect(yielded).to be true
171+
end
172+
173+
it "resets the notifier back to what it originally was when the block completes, even if an error was raised" do
174+
expect {
175+
RSpec::Support.with_failure_notifier(append_to_failures_array_notifier) do
176+
raise "boom"
177+
end
178+
}.to raise_error("boom")
179+
180+
expect { notify(error) }.to raise_instead_of_appending_to_failures_array
181+
end
182+
end
120183
end
121184
end

spec/spec_helper.rb

+3
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
require 'rspec/support/spec'
22
RSpec::Support::Spec.setup_simplecov
3+
4+
RSpec::Matchers.define_negated_matcher :avoid_raising_errors, :raise_error
5+
RSpec::Matchers.define_negated_matcher :avoid_changing, :change

0 commit comments

Comments
 (0)