Как определить методы, которые выходят или отменяются - PullRequest
10 голосов
/ 11 августа 2011

У меня есть метод, запускаемый из CLI, который имеет несколько логических путей, которые явно выходят или прерываются.Я обнаружил, что при написании спецификаций для этого метода RSpec помечает его как сбойный, поскольку выходы являются исключениями.Вот простой пример:

def cli_method
  if condition
    puts "Everything's okay!"
  else
    puts "GTFO!"
    exit
  end
end

Я могу обернуть спецификацию в лямбду с should raise_error(SystemExit), но это игнорирует любые утверждения, которые происходят внутри блока.Чтобы было ясно: я не проверяю сам выход, но логику, которая происходит до него.Как я могу пойти по поводу спецификации этого типа метода?

Ответы [ 3 ]

6 голосов
/ 17 августа 2014

Новый ответ для покрытия ожидаемого синтаксиса Rspec 3.

Тестирование выхода

Просто для проверки того, что вы действительно хотите (т.е. вы не проверяете исключение или ответ значения), что было выведено в STDOUT.

Когда condition ложно

it "has a false condition" do
  # NOTE: Set up your condition's parameters to make it false
  expect {
    begin cli_method
    rescue SystemExit
    end
  }.to output("GTFO").to_stdout # or .to_stderr
end

Когда condition истинно

it "has a true condition" do
  # NOTE: Set up your condition's parameters to make it true
  expect {
    begin cli_method
    rescue SystemExit
    end
  }.to output("Everything's okay!").to_stdout
end

Обратите внимание, что output("String").to_... может принять Regex например.

output(/^Everything's okay!$/).to_stdout

Может также захватывать с stderr например.

output("GTFO").to_stderr

(что лучше для отправки, например, для ОП).

Тестирование выхода

Вы можете отдельно проверить, что ложное условие также повышает SystemExit

it "exits when condition is false" do
  # NOTE: Set up your condition's parameters to make it false
  expect{cli_method}.to raise_error SystemExit
end

it "doesn't exit when condition is true" do
  # NOTE: Set up your condition's parameters to make it true
  expect{cli_method}.not_to raise_error SystemExit
end
6 голосов
/ 11 августа 2011

Просто поместите свои утверждения вне лямбды, например:

class Foo
  attr_accessor :result

  def logic_and_exit
    @result = :bad_logic
    exit
  end
end

describe 'Foo#logic_and_exit' do
  before(:each) do
    @foo = Foo.new
  end

  it "should set @foo" do
    lambda { @foo.logic_and_exit; exit }.should raise_error SystemExit
    @foo.result.should == :logics
  end
end

Когда я запускаю rspec, он правильно говорит мне:

expected: :logics
     got: :bad_logic (using ==)

Есть ли случаи, когда это не сработало бы для вас?

РЕДАКТИРОВАТЬ: Я добавил вызов 'exit' внутри лямбды, чтобы изменить случай, когда logic_and_exit не выходит.

EDIT2: Еще лучше, просто сделайте это в своем тесте:

begin
  @foo.logic_and_exit
rescue SystemExit
end
@foo.result.should == :logics
2 голосов
/ 11 августа 2011

Я могу обернуть спецификацию в лямбда-код с помощью allow_error (SystemExit) но это игнорирует любые утверждения, которые происходят внутри блока.

Я не вижу разницы, проводя тесты внутри или снаружи лямбды. В любом случае сообщение об ошибке немного загадочно:

def cli_method(condition)
  if condition
    puts "OK"
  else
    puts "GTFO"
    exit
  end
end

describe "cli_method" do
  context "outside lambda" do
    # passing
    it "writes to STDOUT when condition is false" do
      STDOUT.should_receive(:puts).with("GTFO")
      lambda {
        cli_method(false)
      }.should raise_error(SystemExit)
    end

    # failing
    it "does not write to STDOUT when condition is false" do
      STDOUT.should_not_receive(:puts).with("GTFO")
      lambda {
        cli_method(false)
      }.should raise_error(SystemExit)
    end
  end
  context "inside lambda" do
    # passing
    it "writes to STDOUT when condition is false" do
      lambda {
        STDOUT.should_receive(:puts).with("GTFO")
        cli_method(false)
      }.should raise_error(SystemExit)
    end

    # failing
    it "does not write to STDOUT when condition is false" do
      lambda {
        STDOUT.should_not_receive(:puts).with("GTFO")
        cli_method(false)
      }.should raise_error(SystemExit)
    end
  end
end

 # output
.F.F

Failures:

  1) cli_method outside lambda does not write to STDOUT when condition is false
     Failure/Error: lambda {
       expected SystemExit, got #<RSpec::Mocks::MockExpectationError: (#<IO:0xb28cd8>).puts("GTFO")
           expected: 0 times
           received: 1 time>
     # ./gtfo_spec.rb:23:in `block (3 levels) in <top (required)>'

  2) cli_method inside lambda does not write to STDOUT when condition is false
     Failure/Error: lambda {
       expected SystemExit, got #<RSpec::Mocks::MockExpectationError: (#<IO:0xb28cd8>).puts("GTFO")
           expected: 0 times
           received: 1 time>
     # ./gtfo_spec.rb:39:in `block (3 levels) in <top (required)>'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...