🍉

testdouble/cypress-rails と shakacode/cypress-on-rails の実体

2021/09/18に公開

CypressというイケイケE2EテストフレームワークをRailsに対向させて試験するための補助ライブラリとして、

という2つの似た名前のライブラリがある。

どっちも利用実績はそれなりにあるのだけど、設計思想が結構違うっぽいので、そのメモ。

2つのライブラリに共通する設計思想

  • Railsアプリケーションに、Cypress側からRails側に何かを命令するためのエンドポイントをこっそり追加してHTTPサーバーを起動する
  • Cypress側から、テスト開始時など必要なタイミングでHTTPリクエストを送る
    • HTTPリクエストを受けて、Ruby側の処理(テストデータの作成・破棄など)を行う

cypress-rails

https://github.com/testdouble/cypress-rails

テストデータの作成・削除について

これがcypress-railsの最大の特徴で、DatabaseCleanerに依存せず、ActiveRecordのtransactional test fixtureをそのまま (ActiveRecord::TestFixturesモジュールをコピペして) 利用している。

ActiveRecordのバックエンドのDBコネクションを共有することで、トランザクションの中のテストデータも見える、みたいなアレ。 lock_thread = true などのRailsのシステムテストが利用しているやつが、cypress-railsにはきれいにコピペ実装されている。(動作確認してみた記事がこれ

GET /cypress_rails_reset_state呼ばれた後の、最初にRailsがリクエストを受けたタイミングで、リセット処理が行われる。(呼んだ瞬間ではないので、CypressのbeforeEachのタイミングとは大きくずれることがある!!)

fixturesやFactoryBotでのテストデータ差し込みは after_transaction_start あたりでやるのがよいだろう。

ただ、CypressのbeforeEachで「リセットしてね!」とHTTPリクエストをする際に、どのテストケースかというメタデータは送られておらず、個々のテストケースで使用するテストデータを変えることはできなさそうだ。

cypress-on-rails

https://github.com/shakacode/cypress-on-rails

  • Railsサーバーはユーザが手で起動する必要がある。
    • RAILS_ENVはtestではなくdevelopment
      • CYPRESSという環境変数で使用するデータベースをテスト用に変える
    • cypress-railsはRailsアプリケーションをラップするRackアプリケーションをpumaに指定してサーバー起動していたのに対して、cypress-on-railsはRailsアプリケーションに直接 use してミドルウェアを追加しているだけ。
  • POST /__cypress__/command という、コマンド注入の口をつくる。

cypress-on-railsは Cypress側からRuby側の処理を呼ぶ という性格が強い。

evalだってすることができる。ワイルドだろぉ〜
https://github.com/shakacode/cypress-on-rails/blob/v1.11.0/lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js#L31

テストデータの作成・削除について

基本的には、「これこれのFactoryBot定義をもとにテストデータを作れ」って命令をする。READMEに書いてあるとおりの実装。

https://github.com/shakacode/cypress-on-rails/blob/master/lib/cypress_on_rails/smart_factory_wrapper.rb

cypress-railsのように、トランザクションの中でテストデータを作ったりDBコネクションを共有したり、といったことは一切していない。本当にただFactoryBotでテストデータを実際にDBにコミットするだけ。
なので、

クリーンアップも「データを消してね」って命令をする。実装はDatabaseCleanerのtruncationストラテジ。https://github.com/shakacode/cypress-on-rails/blob/v1.11.0/lib/generators/cypress_on_rails/templates/spec/cypress/app_commands/clean.rb#L3

個々のテストケースごとにテストデータを変えることは難なくできる。
ただし、cypress-railsがトランザクションのロールバックでデータリセットするのに比べて、cypress-on-railsは実際にTRUNCATE TABLEを実行してデータリセットするため、テーブル数が多いアプリケーションでは、とても時間を要するテストになる。

まとめ

cypress-railsは、Railsのシステムテストに近い状態でCypressのテストが動く。
cypress-on-railsは、Railsとしてはテストされているとは思っていない環境(RAILS_ENV=development)でCypressのテストが動く。

Discussion