要点
- RSpec3.7で追加されたSystemSpecはスクショを自動で保存してくれる機能がある
- Rails6ではRSpec4系の使用が推奨されている
- 解決方法は
rails_helper.rb
パッチをあてる - なぜ?を追ってみたけど、わからなかった
- 他の理由で失敗するケースもある模様
System Specのスクリーンショット保存機能
RSpec 3.7から追加された System Specでは、テスト失敗時に自動でスクリーンショットを保存してくれます。
この機能はRailsのシステムテストに組み込まれているので、feature specのようにcapybara-screenshotなどによるサポートを手動で設定する必要がありません。
Rails 5.1以降のシステムテストをRSpecで実行する(翻訳)|TechRacho
Rails6ではRSpec4の使用が推奨されている
rspec-railsのイシューにもおなじ問題が上がっていました。このスレッドで解決できる ?
とおもったのですが、「rspec-rails4.0で試してみてほしい」「完璧に動いたよ、サンキュー!」でおわっていました。Rails6にはRSpec4という組み合わせが推奨のようですね。
解決方法
以下の記事で、原因と解決するためのパッチが説明されていました。
rails 6.0.0 と rspec-rails 3.8.2 の組み合わせだと Capybara.reset_sessions! を呼んだ後に save_screenshot が呼ばれるので、スクリーンショットの内容が真っ白になります。
Rails アプリケーションの不安定なテストを撲滅したい 〜system spec のデバッグ方法とテストを不安定にさせる要因〜 - あらびき日記
rails_helper.rbにパッチをあてる
さきほどの記事にはパッチコードはあったのですが、「どこに書けばいいか」は明記されておらず、迷いました
rails_helper.rb
に書いてあげると動作することがわかりました。
module SystemHelper
extend ActiveSupport::Concern
included do |example_group|
# Screenshots are not taken correctly
# because RSpec::Rails::SystemExampleGroup calls after_teardown before before_teardown
example_group.after do
take_failed_screenshot
end
end
def take_failed_screenshot
return if @is_failed_screenshot_taken
super
@is_failed_screenshot_taken = true
end
end
RSpec.configure do |config|
config.include SystemHelper, type: :system
end
なぜ?を追ってみたが…
パッチコードをみたときに、「うーん ?」何をしているのか、なぜ直るのかがわかりませんでした。「Capybara.reset_sessions! を呼んだ後に save_screenshot が呼ばれる」というキーワードでしらべてみました。
…
def before_teardown
take_failed_screenshot
ensure
super
end
def after_teardown
Capybara.reset_sessions!
ensure
super
end
TestHelpers::SetupAndTeardownモジュールにたどりついて、それでも ?で力尽きました(笑)
理由が気になる…。
まとめ
- RSpec4はbetaだし、あげると既存のテストが壊れる可能性もある。
- スクショが保存できればそれでいい。
- RSpec4が来るまで動いてくれたらOK!
- 上記にあてはまるようであれば、今回の対応でよいのではとおもいました。
他の理由で失敗するケースもある
遭遇はしたことないのですが、パスの長さがエラーの問題になるケースもあるようでした。(詳細未調査)