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)