Как специфицировать методы, которые выходят или прерываются
У меня есть метод, который запускается из CLI, который имеет некоторые логические пути, которые явно выходят или прерываются. Я обнаружил, что при написании спецификаций для этого метода RSpec отмечает это как сбоя, потому что выходы являются исключениями. Вот пример с голой костью:
def cli_method
if condition
puts "Everything okay!"
else
puts "GTFO!"
exit
end
end
Я могу обернуть спецификацию в лямбда с помощью should raise_error(SystemExit)
, но это игнорирует любые утверждения, которые происходят внутри блока. Чтобы быть ясным: я не тестирую сам выход, а логику, которая происходит до него. Как я могу описать этот тип метода?
Ответы
Ответ 1
Проще говоря, ваши утверждения за пределами лямбда, например:
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 ==)
Есть ли случаи, когда это не сработает для вас?
EDIT: Я добавил вызов 'exit' внутри лямбда, чтобы передать случай, когда logic_and_exit
не выходит.
EDIT2: Еще лучше, просто сделайте это в своем тесте:
begin
@foo.logic_and_exit
rescue SystemExit
end
@foo.result.should == :logics
Ответ 2
Новый ответ для покрытия Rspec 3 ожидает синтаксиса.
Тестирование вывода
Просто чтобы проверить, что вы на самом деле хотите (т.е. вы не проверяете исключение или ответ на значение), то, что было выведено на STDOUT.
Если condition
false
it "has a false condition" do
# NOTE: Set up your condition 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 parameters to make it true
expect {
begin cli_method
rescue SystemExit
end
}.to output("Everything okay!").to_stdout
end
Обратите внимание, что output("String").to_...
может принимать Regex
например.
output(/^Everything okay!$/).to_stdout
Он также может захватывать от stderr
например.
output("GTFO").to_stderr
(Это было бы лучше, если бы вы отправили его для примера OP.)
Тестирование выхода
Вы можете отдельно проверить, что ложное условие также вызывает SystemExit
it "exits when condition is false" do
# NOTE: Set up your condition 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 parameters to make it true
expect{cli_method}.not_to raise_error SystemExit
end
Ответ 3
Я могу обернуть спецификацию в лямбда с помощью raise_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)>'