Stop using Page Objects and Start using App Actions
ページオブジェクト
ページオブジェクトの利点
1. 全てのセレクタを1箇所に集めておける
2. テストがページとやり取りする方法を標準化する
HTMLのUIとアプリケーションコードは強く結合している
render がDOMを返す
ページオブジェクトとHTMLは雑に結合してる
セレクタでくっつけてるけどリンターやコンパイラーなどはない
ページオブジェクトとテストは強く結合している
はい
ページオブジェクトの問題
1. メンテナンスがキビい、アプリケーション開発から時間を奪う。テストを書くためにページオブジェクトが十分にドキュメント化されることはない
2. アプリケーション内部の状態とは別の状態をテストにもたらす。テストの理解とテストの失敗をわかりづらくする
3. 複数のユースケースを統一されたインターフェイスにする、それを条件分岐に落とし込むのはアンチパターン
4. アプリケーションのUIを実際に操作するので遅い
アプリケーションアクション
テストから状態を直接注入する。window 経由でモデルを参照出来るようにする。
アプリケーションのアクションを関数としてまとめる
単なる関数なので別のファイルに切り出して共通化できる
ドキュメントがかける
使うときに補完が効く
便利
テストコードをDRYにする
これはページオブジェクトのようなオブジェクトを作って操作のメソッドを生やさず、各操作を関数として export してそれを import して使いましょう。という対比をさせている。
フォーカスされたエラー
この流れで進む、UIをいじるとここの1のデータのセットアップ部分の途中でエラーが起きて「なぜ...」となるけどアプリケーションアクションで状態を注入すると1でエラーになることは基本ない。
1. 内部の状態をいじる
2. その状態に応じた操作をテストする
状態を直接いじれることによってより特定の機能にフォーカスしたテストを書け、エラーが起きたときに何が壊れてるのか分かりやすくなるみたいな話っぽい。
例えば、ログイン画面がぶっ壊れたときアプリケーションアクションでログインした状態を作っておけばログインでエラーにはならない。一方UIを操作してログインするページオブジェクト式だとログイン画面が壊れると全てのログイン後の操作のテストが壊れる。
アプリケーションコードの制限
大量のアクションを爆速で呼ぶ弊害で副作用のある感じのrenderがぐっちゃぐちゃになるみたいな話?
解決策として
アクション呼ぶんだあと期待したUIになる、のを交互に書いていって待つようにしましょう
期待するXHRが発生するまでまとう
メソッドをspyしておいて期待する呼ばれたら続きをやるみたいにしよ
全部一気に流すわけじゃなくて都度待つ必要があるものを待つのが大事みたいな話をしてそう
あとは
ログインページをテストするときE2Eテストはユーザーが使うようにUIを使って操作すべき
それ以外でログインが必要なユーザーの操作の流れをテストしたいときは、UI使ってログインする操作を何度も何度も行わなくてよい、 cy.request コマンドなどで直接ログインのXHR投げればよい
この記事のまとめ
ページのUIを操作するページオブジェクトから、内部APIを使ってモデルを直接いじるアプリケーションアクションを使うと、いろいろ便利という話だった
データを整えるためにUIを操作しないのでテストが早くなる
テストがアプリケーションのリファクタリングの恩恵をうけるようになった。アプリケーションの内部のAPIからより便利な情報とドキュメントがもたらされ、それによってアプリケーションコードのためのE2Eを書きやすくなる
変わりやすい不安定な雑な結びつきのUI経由の操作を避けて、よりアプリケーションとの結びつきのつよい長持ちする内部APIを使える。
ページオブジェクトとアプリケーションコードで2つの状態を抱えずに、無理して操作するための分岐もなく、DevToolのコンソールから叩く感じでアプリケーションコードを直接叩くだけのグルーコードを書くだけでよい。べんり。
アプリケーションアクション前提として問われている構造 hanachin.icon
SPAでデータとrenderが完全に分離されていることを想定して書かれていそう。
アプリケーションコードで扱うデータを操作する部分をコンテナ、viewを表示する部分をコンポーネントと完全に分離していればアプリケーションアクションから状態を注入できそうだけどわりと内部APIが分離されてなくて密な感じの場合難しいのでは、という感想。
データ投入をコードからやるのE2Eとして違和感ないですかねhanachin.icon
E2Eでデータ投入する部分をアプリケーションアクションでやる部分に若干違和感を覚える。実際はUIを操作していて、アプリケーションアクションみたいな操作をしているわけではないわけで。一方、アプリケーションコードの操作をそのまま使っているわけだから、データを投入するまでの部分がUIからかコードからかが違うだけで実際の操作と変わらないとも言えそう。
UIから何かデータを作る部分は作る部分で別でE2Eテストを書けばまあ問題はないのか。
あとログインに関しては毎回ログインページをテストしたいわけではないので、それはそうという感じですね、はい。
一方で状態をアプリケーションアクションから操作するコードを書くぐらいならUI操作をつらつらと並べてしまって、雑にマシンパワーで並列に動かす方が楽ではと思ってしまわなくもない。その場合はランダムフェイル増えそうだけどまあ、二度がけするとかすればよいので...
SPAならJavaScriptから直接モデルいじれるからよいが
例えばRailsのアプリケーションをテストしたい場合とかはデータの初期投入をどうすればよいのか、つらそう。
最近同僚とevalするエンドポイントを生やせばよいのでは、みたいな話をしていた。
多分そのevalするエンドポイントに向かってRubyのコード投げるみたいな感じでよいと思うが
投げているRubyのコードがちゃんと動くかはわからない
モデルもJavaScriptで実装されている場合はちゃんと型検査が通ったりドキュメントがひけたりするがRuby in JSではそんなことは無理そう。ただの文字列なので。