Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Exit code matcher for rspec 3
RSpec::Matchers.define :terminate do |code|
actual = nil
def supports_block_expectations?
true
end
match do |block|
begin
block.call
rescue SystemExit => e
actual = e.status
end
actual and actual == status_code
end
chain :with_code do |status_code|
@status_code = status_code
end
failure_message_for_should do |block|
"expected block to call exit(#{status_code}) but exit" +
(actual.nil? ? " not called" : "(#{actual}) was called")
end
failure_message_for_should_not do |block|
"expected block not to call exit(#{status_code})"
end
description do
"expect block to call exit(#{status_code})"
end
def status_code
@status_code ||= 0
end
end
describe HerpDerps do
it 'exits cleanly' do
# expecting call to `exit`
-> expect{ described_class.run }.to terminate
end
it 'exits with non-zero status code' do
#expecting call to `abort` or `exit(false)`
-> expect{ described_class.run }.to terminate.with_code(1)
end
end
@bazay

This comment has been minimized.

Copy link

@bazay bazay commented Nov 20, 2015

Great script, thanks for writing! Just noticed the following things in my implementation.

'failure_message_for_should' and 'failure_message_for_should_not' have been depreciated in Rspec 3 and can be replaced with 'failure_message' and 'failure_message_when_negated', respectively.

See below:

RSpec::Matchers.define :terminate do |code|
  actual = nil

  def supports_block_expectations?
    true
  end

  match do |block|
    begin
      block.call
    rescue SystemExit => e
      actual = e.status
    end
    actual and actual == status_code
  end

  chain :with_code do |status_code|
    @status_code = status_code
  end

  failure_message do |block|
    "expected block to call exit(#{status_code}) but exit" +
      (actual.nil? ? " not called" : "(#{actual}) was called")
  end

  failure_message_when_negated do |block|
    "expected block not to call exit(#{status_code})"
  end

  description do
    "expect block to call exit(#{status_code})"
  end

  def status_code
    @status_code ||= 0
  end
end

Also, the '->' isn't necessary meaning you can simply call:

expect{ described_class.run }.to terminate.with_code(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment