Techioz Blog

Rspec は、合格したテストも含め、–only-failure を指定してすべてのテストを再実行します

概要

Selenium テスト用の rspec をラップする Ruby gem があります。以前の実行での失敗を再実行することで再試行ロジックを実装しようとしていますが、2 回目の実行ではすべてが再試行されるだけで、2 回目の実行で example_status_persistence_file_path の場所を含む spec_helper が読み込まれていないためだと思います。

デバッグ用の Puts ステートメントを spec_helper に追加しました。これが 2 回呼び出されず、1 回だけ呼び出されていることがわかります。ただし、example_status_persistence_file_path が設定されていない場合に表示されるエラーも表示されないため、どうすればよいかわかりません。

spec_helper.rb

RSpec.configure do |config|
  config.example_status_persistence_file_path = "logs/LO_RunResults.txt"
end

my_spec.rb

it "should pass" do
  expect(true).to be true
end

it "should fail" do
  expect(false).to be true
end

rspec_runner.rb

test_results_file = "#{File.expand_path(Dir.pwd)}/logs/RunResults.txt"
File.delete(test_results_file) if File.exist?(test_results_file)

args = %w(-r spec_helper --order defined --format CustomFormatter --format documentation)
RSpec::Core::Runner.run(args, $stderr, $stdout)

# RunResults.txt is generated from previous run

args = %w(-r spec_helper --order defined --format CustomFormatter --format documentation --only-failures)
RSpec::Core::Runner.run(args, $stderr, $stdout)

Ruby rspec_runner.rb を実行すると、次の出力が得られます。

#################### Running spec_helper ####################

Test Suite - my_spec
  Positive Tests
    should pass
    should fail (FAILED - 1)

Failures:

  1) Test Suite - my_spec Positive Tests should fail
     Failure/Error: expect(false).to be true
     
       expected true
            got false
     # ./spec/my_spec.rb:59:in `block (3 levels) in <top (required)>'

Finished in 0.06265 seconds (files took 0.71696 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/my_spec.rb:58 # Test Suite - my_spec Positive Tests should fail

Run options: include {:last_run_status=>"failed"}

Test Suite - my_spec
  Positive Tests
    should pass
    should fail (FAILED - 2)

Failures:

  1) Test Suite - my_spec Positive Tests should fail
     Got 2 failures:

     1.1) Failure/Error: expect(false).to be true
          
            expected true
                 got false
          # ./spec/my_spec.rb:59:in `block (3 levels) in <top (required)>'

     1.2) Failure/Error: expect(false).to be true
          
            expected true
                 got false
          # ./spec/my_spec.rb:59:in `block (3 levels) in <top (required)>'

  2) Test Suite - my_spec Positive Tests should fail
     Got 2 failures:

     2.1) Failure/Error: expect(false).to be true
          
            expected true
                 got false
          # ./spec/my_spec.rb:59:in `block (3 levels) in <top (required)>'

     2.2) Failure/Error: expect(false).to be true
          
            expected true
                 got false
          # ./spec/my_spec.rb:59:in `block (3 levels) in <top (required)>'

Finished in 0.03786 seconds (files took 0.79882 seconds to load)
4 examples, 2 failures

Failed examples:

rspec ./spec/my_spec.rb:58 # Test Suite - my_spec Positive Tests should fail
rspec ./spec/my_spec.rb:58 # Test Suite - my_spec Positive Tests should fail


Process finished with exit code 0

解決策

RSpec にサンプルのリロードを強制するために、2 つの実行の間に RSpec.clear_examples を使用してみてください。

test_results_file = "#{File.expand_path(Dir.pwd)}/logs/RunResults.txt"
File.delete(test_results_file) if File.exist?(test_results_file)

args = %w(-r spec_helper --order defined --format CustomFormatter --format documentation)
RSpec::Core::Runner.run(args, $stderr, $stdout)

RSpec.clear_examples

# RunResults.txt is generated from previous run

args = %w(-r spec_helper --order defined --format CustomFormatter --format documentation --only-failures)
RSpec::Core::Runner.run(args, $stderr, $stdout)

ドキュメントは参考のためにここにあります: https://www.rubydoc.info/github/rspec/rspec-core/RSpec.clear_examples。