Rails 5: WebSocketのマルチセッションをMiniTestとシステムテストでテストする(翻訳)

概要 原著者の許諾を得て翻訳・公開いたします。 英語記事: How to Test Multiple WebSocket Sessions With Minitest and Rails 5 System Tests 原文公開日: 2017/12/17 著者: Kieran Eglin サイト: https://kierancodes.com/ Rails 5: WebSocketのマルチセッションをMiniTestとシステムテストでテストする(翻訳) 状況 やりとりにWebSocketを使うチャットアプリがあり、サブスクライブ先のソケットをディクテーションするためのログインシステムがあるとします。通常のシステムテストを使って、メッセージが往復していることを確認するにはどうしたらよいでしょうか? MiniTestと、Capybaraを使うRails 5のシステムテストが前提です。 最初にやってみたこと Capybaraのopen_new_windowを使って新しいブラウザタブを開き、そこでサインインして操作します。within_windowでタブ間を切り替えることもできます。 これは一見うまくいきそうに見えますが、何人かのユーザーがsocketにサブスクライブする方法によっては、タブのオープン/サインアウト/新しいユーザーとしてログインしてメッセージを送信するなどのアプリ操作がごちゃごちゃになってしまいそうです。それに、このやり方は本質的に何か間違っているのではないかと思えてきませんか。 今回の解決法 実はCabpybaraのセッションを複数作成して、それらを切り替えることができるのです。 セッションを1つ作成すると新規ウィンドウが1つ初期化され、cookieやローカルストレージなどが完全に他と分離されます。この方法はすっきりしていますし、「より正しい」ソリューションのように思えます。なお、このデフォルトセッション名は、よりによって:defaultです。セッション名の取得や設定はCapybara.session_nameで行えます。 以下はこれを行うためのテストコード例です。 test ‘チャットルームのメッセージがリアルタイムで更新される’ do login_as @bob visit ‘/chatroom’ Capybara.session_name = :new_window # この名前はまったく自由に設定できます # ここからは完全に新しいブラウザセッションです! login_as @sue visit ‘/chatroom’ submit_message ‘Hey, Bob!’ Capybara.session_name = :default # ここから元のBobのセッションに戻ります assert page.has_content?(‘Hey, Bob!’) 私にはこっちの方がずっとよさそうに思えますし、実際しっかり動きます。 しかしこの書き方はいくらなんでも見苦しすぎます。 もう少しコードを減らして読みやすくしたい場合、私はtest_helper.rbに置いている次のシンプルなメソッドみたいな方法が好きです。 def within_session(name) old_session_name = Capybara.session_name Capybara.session_name = name.to_sym yield Capybara.session_name = old_session_name end これを使って、先ほどのテストを以下のように簡潔に書けます。 test ‘Chatroom messages update in real time’ do login_as @bob visit ‘/chatroom’ within_session :new_window do login_as @sue visit ‘/chatroom’ submit_message ‘Hey, Bob!’ end assert page.has_content?(‘Hey, Bob!’) これでさらによくなったと思いませんか? クリーンアップ 最後に、テストスイート実行完了後に新規ブラウザウィンドウが開きっぱなしになっていることがあります。問題というほとのものではありませんが、やはり好きになれません。以下のような方法でウィンドウを簡単に閉じられます。 def close_session(name, original_session = :default) Capybara.session_name = name.to_sym page.driver.quit Capybara.session_name = original_session end 次のように、テストの終わったウィンドウに対して使うこともできます。 close_session :new_window Happy coding! 関連記事 Rails 5.1以降のシステムテストをRSpecで実行する(翻訳) TestProf: Ruby/Railsの遅いテストを診断するgem(翻訳)