1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rubyで、テスト対象のコードで exit していると RSpec がそこで正常終了する

Posted at

並行で行っている RSpec のテストの実行数がなぜか実行ごとに異なるという問題が発生した。実行ログを調査したところ、テストの途中で RSpec が正常に終了していることがわかった。原因はテストコード中で exit を実行していること。特に rake タスクのテストとかで結構あると思う。

例えば、このようなコードがあり

main.rb
def assert_some_conditions!(conditions)
  if conditions == 1
    exit
  end
end

このようなテストを書いた時、

main_spec.rb
require 'rspec'
require './main'

RSpec.describe 'assert_some_conditions!' do
  it 'be nil when 1(まちがい)' do
    expect(assert_some_conditions!(1)).to be_nil
  end

  it 'be nil when 0' do
    expect(assert_some_conditions!(0)).to be_nil
  end
end

二つ目の it が実行されないままテストが正常終了する!!

$ bundle exec rspec main_spec.rb -fd

assert_some_conditions!

Finished in 0.00046 seconds (files took 0.04432 seconds to load)
1 example, 0 failures

こんなふうになる。 exit を通った時点で RSpec ごと終了するので何もテスト実行されてない。テストが増えてくると結構気づかないとおもう。怖い。並行テスト&ある程度ランダムな割り振り(たまたまCIが毎回の実行時間に基づいて並行を割り振ってたので微妙なランダム)で RSpec を走らせていたのでばらつきに気づいたけど、そうじゃなかったら気づかなかったかもしれない。

対処法

exitStandardError ではない 例外 SystemExit を発生させているので、これをキャッチして投げ直せばいい。

exit は例外 SystemExit を発生させることによってプログラムの実行を終了させますので、必要に応じて begin 節で捕捉することができます。

コンフィグに書いちゃえば安心かも

main_spec.rb
RSpec.configure do |config|
  config.around(:example) do |example|
    example.run
  rescue SystemExit
    fail '予期しない exit が発生しました'
  end
end

これ書いておけばちゃんと失敗するし最後までテストが実行される。

$ bundle exec rspec main_spec.rb -fd

assert_some_conditions!
  be nil when 1(まちがい) (FAILED - 1)
  be nil when 0

Failures:

  1) assert_some_conditions! be nil when 1(まちがい)
     Failure/Error: fail '予期しない exit が発生しました'

     RuntimeError:
       予期しない exit が発生しました
     # ./main_spec.rb:8:in `rescue in block (2 levels) in <top (required)>'
     # ./main_spec.rb:6:in `block (2 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # SystemExit:
     #   exit
     #   ./main.rb:3:in `exit'

Finished in 0.00095 seconds (files took 0.04431 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./main_spec.rb:13 # assert_some_conditions! be nil when 1(まちがい)

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?