読書メモ: フロントエンド開発のためのテスト入門
テスト対象(モジュール)
1. ライブラリが提供する関数
2. ロジックを担う関数
3. UIを表現する関数
4. Web API クライアント
5. API サーバー
6. DB サーバー
テストレベル
どの範囲をカバーしたテストか
静的解析
モジュールの内部検証 や モジュール間連携の不整合に使う
単体テスト
モジュール単体の機能に使う
独立しているためコーナーケースの検証に使いやすい
結合テスト
1-4, 2-3 などモジュールをつなげて提供する機能に使う
テスト対象を効率よくカバーできる
E2Eテスト
1-6を通してヘッドレスブラウザ+UIオートメーションで実施
テストタイプ
テストの目的に応じて何をテストするかを決める
機能テスト
機能に不具合がないか
FEはUIの操作が起点となるため機能テスト ≒ インタラクションテスト
非機能テスト
アクセシビリティ
チェックボックス(type="checkbox")としてチェックできる
キーボード操作
読み上げ
ホワイトボックステスト
リグレッションテスト
特定時点から前後の差分を検出して不具合が発生していないかを検証するテスト
VRT,
テスト戦略
トレードオフ
実行時間,メンテコスト <-> 実際の挙動に近い忠実性が高いテスト
例
アイスクリームコーン型
アンチパターン
運用コストが高い
不安定なテスト
テストピラミッド
単体テストを厚く
安定かつ高速
テスティングトロフィー
なぜテストを書くのか
信頼性のため
バグによりサービスに対する信用が下がる
ユーザーが離脱する
負債を抱えないため
求められる要件に伴ってコードも変わるため、どんなコードも負債になりうる
リファクタリングが求められる
変更箇所以外が壊れていないことを担保できる
Dependabotなどでバージョンアップした結果壊れていないことを担保するため
コード品質に自信を持つため
テストを書く際にコード品質を見直す機会になる
テストが書きづらいコードは悪いコードの可能性が高い
往々に複雑なことをしようとしている
Webアクセシビリティの見直しになる
テスト対象の取得にアクセシビリテ由来のAPIを使う機会が多いため
ドキュメントとして残せるため
タイトルと振る舞いが書いてある
単体テスト
関数のテストと同じようにprops -> UI の単体テストを書くことが可能
コーナー消すで例外処理
統合テスト(integration)
ex.
セレクトボックスの操作する
URLの検索クエリが変化する
検索クエリの変化により、データ取得APIが呼ばれる
一覧表示内容が更新される
できるだけ狭い範囲でテストをした方がシンプルで明確になる
フロントエンドの開発対象(ドメイン)はUI ≒ ユーザー操作とそれによる状態遷移 > 画面表示 (≠画面の表示のみ, ロジックはない)
インタラクティブなUI
操作のバリデーション
form入力バリデーション
fyi: ドメインとはユーザーの何らかの活動や関心と関係がある。ユーザーがプログラムを適用する対象領域
インタラクティブな操作を伴うので結合テスト
x: 🤔ヘッドレスブラウザを立ち上げてめんどくさいなぁ
o: 仮装ブラウザ環境でテストできる
UIコンポーネントテスト
アクセシビリティテストになりうる
支援技術ユーザーが識別できる要素を使うことで双方のテストができる
マウスユーザー ⊂ 支援技術ユーザー
testing-lib
暗黙的なロールを取得するAPI(getByRole)を使う
getの範囲をscreenから絞りたい場合はwithin関数で絞り込む
<form>にaria-labelledbyを与えないとrole="form"にはならない
code:tsx
<form aria-labelledby={id} >
<h2 id={id}
</form
roleがわからない時は logRolesを実行
coverage
stmts(命令網羅率)
全てのステートメント(命令)が少なくとも1回実行されたか
Branch(分岐網羅率)
全ての条件分岐が少なくとも1回通過したか
条件分岐に対してテストが書かれていないことをの発見
Funcs(関数網羅率)
全ての関数が少なくとも1回呼び出されたか
exportされていない関数の発見
Lines(行網羅率)
全ての行を少なくとも1回通過したか
テスト実践
userEvent.setup()はglobalな箇所(describe外)に書く
毎回render 書くのが面倒な時
setup関数という命名の関数を切る
beforeEachでやれば ?
推奨されていない
複数テストを書いた時に暗黙的に実行されているように見えて明示的ではない
beforeEachで mutableな変数(let)を使うと値の変更のtracingが大変
describeでnestさせたくない
sorybookをテストコードに再利用する
@storybook/test-runner
JestでStoryを再利用するほうが優れている点
- モジュールモックやスパイが必要なテストが書ける(Jestのモック関数を使用)
- 実行速度が速い(ヘッドレスブラウザを使用しない)
Storybookでinteractiveなテストを書く方が優れている点
・テストファイルを別途用意しなくてもよい(工数が少ない)
・忠実性が高い(ブラウザを使用するのでCSS指定が再現される)
VRTする時に役に立つので絶対に不要なStory以外もcommitする習慣をつける
VRTがあるとglobal cssやレスポンシブ対応のリファクタがやりやすくなる
e2e
外部サービスをmock
テスト対象ブラウザ固有のAPIを含めたテスト
≒UIテスト
外部サービスをmockせずテスト
E2Eテストフレームワークを使用したテストは、安定運用することが難しいとされています。不安定なテストは、ネットワーク遅延やメモリ不足によるサーバーからのレスポンスの遅れなど、原因は様々です。