How to force an RSpec test to fail?
Solution 1:
fail
/raise
will do the trick (they are aliases of each other).
Example
specify "this test fails" do
raise "this is my failure message"
end
Fails with:
1) failing this test fails
Failure/Error: raise "this is my failure message"
RuntimeError:
this is my failure message
Alternatives
If you are thinking of using raise
/fail
in a spec, you should consider that there are probably more explicit ways of writing your expectation.
Additionally, raise
/fail
doesn't play well with aggregate_failures
because the exception short-circuits the block and won't run any following matchers.
Mark a test as pending
If you need to mark a test as pending to make sure you get back to it, you could use the fail
/raise
, but you can also use pending
.
# 🚫 Instead of this:
it "should do something" do
# ...
raise "this needs to be implemented"
end
# ✅ Try this:
it "should do something" do
pending "this needs to be implemented"
end
Assert that a block is not called
If you need to ensure a block is not being executed, consider using the yield
matchers. For example:
describe "Enumerable#any?" do
# 🚫 Instead of this:
it "doesn't yield to the block if the collection is empty" do
[].any? { raise "it should not call this block" }
end
# ✅ Try this:
it "doesn't yield to the block if the collection is empty" do
expect { |b| [].any?(&b) }.not_to yield_control
end
end
Solution 2:
I know that this was asked and answered many years ago, but RSpec::ExampleGroups
has a flunk
method. I prefer this flunk
method to using fail
in the context of testing. Using fail
has an implied code failure (you can see more on that here: https://stackoverflow.com/a/43424847/550454).
So, you can use:
it 'is expected to fail the test' do
flunk 'explicitly flunking the test'
end
Solution 3:
If you want to simulate an RSpec expectation failure rather than an exception, the method you're looking for is RSpec::Expectations.fail_with
:
describe 'something' do
it "doesn't work" do
RSpec::Expectations.fail_with('oops')
end
end
# => oops
#
# 0) something doesn't work
# Failure/Error: RSpec::Expectations.fail_with('oops')
# oops
Note that despite the documentation, fail_with
doesn't actually raise an ExpectationNotMetError
directly, but rather passes it to the private method RSpec::Support.notify_failure
. This is handy when using aggregate_failures
, which (under the hood) works via a custom failure notifier.
describe 'some things' do
it "sometimes work" do
aggregate_failures('things') do
(0..3).each do |i|
RSpec::Expectations.fail_with("#{i} is odd") if i.odd?
end
end
end
end
# => some things
#
# Got 2 failures from failure aggregation block "things":
#
# 1) 1 is odd
#
# 2) 3 is odd
#
# 0) some things sometimes work
# Got 2 failures from failure aggregation block "things".
#
# 0.1) Failure/Error: RSpec::Expectations.fail_with("#{i} is odd") if i.odd?
# 1 is odd
#
# 0.2) Failure/Error: RSpec::Expectations.fail_with("#{i} is odd") if i.odd?
# 3 is odd
# sometimes work (FAILED - 1)