Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
フロントエンドの単体テストの使い方/考え方
Search
Tomoya Kashifuku
March 16, 2023
Programming
0
280
フロントエンドの単体テストの使い方/考え方
Tomoya Kashifuku
March 16, 2023
Tweet
Share
More Decks by Tomoya Kashifuku
See All by Tomoya Kashifuku
Rustでオリジナルnpmパッケージを作ってみよう
tnyo43
0
190
ユーザのためだけじゃない!エンジニアも嬉しいアクセシビリティ改善のための自動テスト
tnyo43
0
560
ルールの運用から始めるフロントエンド開発改善
tnyo43
5
2.8k
Elm でつくるルービックキューブ
tnyo43
1
430
Other Decks in Programming
See All in Programming
SwiftUIで単方向アーキテクチャを導入して得られた成果
takuyaosawa
0
120
Compose でデザインと実装の差異を減らすための取り組み
oidy
1
220
バックエンドのためのアプリ内課金入門 (サブスク編)
qnighy
1
200
[JAWS-UG横浜 #80] うわっ…今年のServerless アップデート、少なすぎ…?
maroon1st
0
140
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
410
混沌とした例外処理とエラー監視に秩序をもたらす
morihirok
18
3.1k
SpringBoot3.4の構造化ログ #kanjava
irof
1
490
ecspresso, ecschedule, lambroll を PipeCDプラグインとして動かしてみた (プロトタイプ) / Running ecspresso, ecschedule, and lambroll as PipeCD Plugins (prototype)
tkikuc
2
2.2k
AWS Lambda functions with C# 用の Dev Container Template を作ってみた件
mappie_kochi
0
210
PHPで学ぶプログラミングの教訓 / Lessons in Programming Learned through PHP
nrslib
4
1.1k
チームの立て直し施策をGoogleの 『効果的なチーム』と見比べてみた
maroon8021
0
170
『改訂新版 良いコード/悪いコードで学ぶ設計入門』活用方法−爆速でスキルアップする!効果的な学習アプローチ / effective-learning-of-good-code
minodriven
29
4.7k
Featured
See All Featured
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
127
18k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
3
370
Why Our Code Smells
bkeepers
PRO
335
57k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
98
18k
Designing on Purpose - Digital PM Summit 2013
jponch
117
7.1k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
174
51k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.4k
Speed Design
sergeychernyshev
25
750
A Modern Web Designer's Workflow
chriscoyier
693
190k
Reflections from 52 weeks, 52 projects
jeffersonlam
348
20k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
Transcript
フロントエンドの単体テストをやる前に知りたい フロントエンドの単体テストの考え方 カシフクトモヤ 2023/03 1
目的 • フロントエンドで実装する単体テストがカバーする範囲を知る • 単体テストで壊れにくいテストを実装するための思想を知る • 思想に基づいた運用方法を考えられるようにする 2
種本(種記事) • 単体テストの考え方 /使い方(Vladimir Khorikov) • React でつくるフォーム UI の単体テストと
TDD • testing-library でユーザの気持ちになって書くフロントエンドのテスト 3
目次 • フロントエンドの単体テストって何? • フロントエンドの単体テストって、具体的にはどうするの? • フロントエンドのテストをうまく運用するにはどうしたらいいの? 4
目次 • フロントエンドの単体テストって何? • フロントエンドの単体テストって、具体的にはどうするの? • フロントエンドのテストをうまく運用するにはどうしたらいいの? 5
フロントエンドで何をテストしたい? • 意図しない見た目の変更が発生してないか検知したい • ロジックが正しいことを確認したい • ユーザの動作によって起こる挙動を確認したい 6
どういうテストで解決できるの? 意図しない見た目の変更が発生してないか検知したい Visual Regression Test (VRT) を使って解決できるかも。 コンポーネント(もしくは画面)のキャプチャを撮って、変更前と比較する。 変更の有無を見た目だけで判断する。 7
クリック クリック 角の形が変わったことを検知したい
どういうテストで解決できるの? ロジックが正しいことを確認したい 単体テストで検査できるかも 関数としてロジックを定義すると出力値ベーステスト (*1) クラスやカスタムフックとしてロジックを持つと出力値ベーステストと状態ベーステスト 8 *1 単体テストの考え方 /使い方
第6.1章 状態 入力値 出力値 ここを検査したい
どういうテストで解決できるの? ユーザの動作によって起こる挙動を確認したい 単体テスト(統合テスト)や E2E テストで検査できるかも (*1)。 ツールを使ってユーザの動作をシミュレートし、ソフトウェアの動作を確認する。 • 表示の変化は状態ベース・テスト •
API 通信や処理の実行はコミュニケーションベース・テスト 9 *1 ここでは、単体テストと統合テストを明確に区別せず、まとめて単体テストと呼ぶこととします。
テストの種類とできること 「単体テストだけ」や「VRT だけ」など、ある一つのみで全てを解決することはできない。 テストの特性に合わせて適切なテストを実装するとよい。 10 VRT 見た目の 変更の検査 ロジックの 正しさ
書き方の正しさ ユーザの動作に対する 正しい応答 画像引用 “https://testingjavascript.com/” 品質保証 〇 実行速度 ▲ 品質保証 ▲ 実行速度 〇
今回のテーマは単体テスト フロントエンドの実装において、単体テストで検査したいのは大きく次の 2つ。 • ロジックの正しさ • ユーザの動作に対する正しい応答 「ロジックの正しさ」の検査はフロントエンドだけの話ではない。 ここではフロントエンドの単体テストを「 ユーザの動作に対する正しい応答
」の検査であると定義する。 11
目次 • フロントエンドの単体テストって何? • フロントエンドの単体テストって、具体的にはどうするの? • フロントエンドのテストをうまく運用するにはどうしたらいいの? 12
「ユーザの動作に対する正しい応答」って何? たとえば、次のようなユースケースのテストを作りたい。 • ユーザが要素に値を入力してボタンをクリックすると、 API リクエストが送られる • チェックボックスを全て選択していないと、ボタンがクリックできない状態になっている • キーボードで
[Ctrl + F] と入力すると、検索窓にフォーカスされる 13
「ユーザの動作」と「正しい応答」を分析する • ユーザの動作 ◦ 操作したい要素を見つける ◦ マウスのクリック ◦ キー入力をする •
正しい応答 ◦ 要素を変化させる ▪ 特定の文字列が表示される /非表示になる ▪ 入力要素がフォーカスされている ◦ API にリクエストを送る / callback 関数を実行する 14
ユーザの動作の再現に使える testing-library testing-library はフロントエンドのテストに用いるツールとして知られている。 React、Vue、Svelte などで動作するライブラリ。 要素を見つける、マウスのクリックやキー入力をするといったユーザの動作をシミュレートできる。
「テストをソフトウェアの使用方法に似せる」という基本方針 にしたがって使うことが推奨されている。 15
要素を見つけるクエリ testing-library は要素を見つけるためのクエリ を提供している。 クエリには優先順位がついていて、優先順位が高いほど「ソフトウェアの使用方法に似た」テストを作れる傾向に ある (*1)。 • getByRole
• getByLabelText • getByPlaceholderText • getByText • getByAltText • getByTitle • getByTestId 16 *1 実装の方針によっては優先順位が低いクエリを使ったほうがいいケースもある。 優先度が高い 低い
要素を見つけるクエリの優先度を考える 17 優先順位を考えるとき、ユーザがどのように要素を見つけるかを考えるのがポイント。 例)『生年月日』の入力要素を見つけるクエリ • getByRole は WAI-ARIA ロールを使って要素を探すクエリ •
getByPlaceholderText はプレースホルダーを使って要素を探すクエリ getByRole を使ったほうがユーザがどのように要素を見つけるかを反映している。
ユーザのアクションを再現する testing-library はユーザの動作を再現するためのライブラリ user-event を提供している。 クリックやキーボードのタイプを、かなり直感的に再現できるようになっている。
18
要素の変化を検知する testing-library/jest-dom というライブラリで、要素の検査ができるようになる。 直感的に状態を確認できる関数を提供している。 実装時に「ユーザが要素の状態を認識する根拠となる状態のあり方」を知らなくてよい。 • toBeInTheDocument (表示されていることを確認) • toHaveFocus
(フォーカスされていることを確認) • toHaveValue (値が入力されていることを確認) • etc… 19
API にリクエストを送る / callback 関数を実行する API のリクエストは MSW などのライブラリを活用してモックサーバを使って検査できる。 callback
関数の検査は jest のモック関数を使って検査できる。 (詳細は省略) 20
テストを実装してみよう 次のようなコンポーネントのテストを実装する。 • 3つの入力要素があって、下の画像のような出力になる 次のようなテストを作る • 適切なデータを入力して『送信』ボタンを クリックすると、props で渡す”submit” が呼ばれる
• 必須項目の『名前』を空欄にして送信すると、 “submit” が呼ばれず警告のメッセージが表示される 21 テスト対象の UI
テストを実装してみよう 適切なデータを入力して 『送信』ボタンをクリックすると、 props で渡す ”submit” が呼ばれる 22
テストを実装してみよう 必須項目の『名前』を 空欄にして(『名前』以外を入力する) 送信すると、 “submit” が呼ばれず 警告のメッセージが表示される 23
本当にテストを実装できるの? 24 一般に、ソフトウェアのテストのしやすさの度合いを「テスト容易性」として表す。さらに分割すると、次のような要 素に分けられる(*1)。 • テスト容易性は実行円滑性(テスト実行での支障の少なさ) • 観測容易性(テスト対象の出力の取得しやすさ) • 理解容易性(テスト対象の理解のしやすさ)
• etc… フロントエンドのテストの難しい場合、多くは(特に状態の)観測容易性が低いからではないかと思う。 *1 https://www.qbook.jp/column/20190410_753.html より引用
観測可能性が高いコードって何? 25 適切な style を与えると、どちらでも同じように実装できる。
観測可能性が高いコードって何? 26 テスト容易性が低い状態であるが、それと同時に マシンリーダビリティが低い状態 でもある。 ラベルと要素が紐づかないので入力要素を観測できない ボタンとして認識されないので観測できない
テスト容易性とマシンリーダビリティ 27 マシンリーダビリティとは機械にとってのコンテンツを読み取りやすさの度合いのこと (*1)。 ブラウザや支援技術などのユーザエージェントがコンテンツを解釈できるようにするためには マシンリーダビリティの向上が欠かせない。 フロントエンドのテストは、 機械がコンテンツを読み取ったり操作をしたり してソフトウェアの動作をシミュレーショ ンする。
マシンリーダビリティが高いほうがテスト容易性が高くなる 傾向にある。 フロントエンドのテストの導入の前に、マシンリーダビリティ(ひいてはアクセシビリティ)の向上を目指すとよい。 *1 Webアプリケーションアクセシビリティ p43-45 より引用
目次 • フロントエンドの単体テストって何? • フロントエンドの単体テストって、具体的にはどうするの? • フロントエンドのテストをうまく運用するにはどうしたらいいの? 28
テストを作る目的を明確にする (単体テストだけでなく)目的が明確でないテストは負債になる。 • テストの目的は何か • 目的を果たすためにはどのように実装すべきか • 誰から見ても理解しやすいか 対象となるソフトウェアやチームの思想によって いいテストのあり方も変わる。
「動くが自明で意味を持たないテスト」「壊れやすいテスト」「自己満足なテスト」は 負債になって、むしろ開発の妨げになる。 29
アクセシビリティのガイドラインを定める アクセシビリティはユーザ体験に影響を与える 外部品質のため。 テスト容易性は開発者体験にのみ影響を与える 内部品質のため。 内部品質を優先させるために外部品質を(著しく)棄損してはいけない。 まずはアクセシビリティのガイドラインを作ってから、それに沿ったテストを考えるのがセンスがよさそ う。 アクセシビリティのガイドラインで規定されていない部分はテストのしやすさを基準に決めてもよい。 30
まとめ フロントエンドのテストは単体テストだけではなく VRT や E2E テストもある。 フロントエンドの単体テストで確認したいのは ユーザの動作に対する正しい応答 。 ユーザの動作に対する正しい応答を検査するようなテストでは、
testing-library をうまく使う必要があ る。使う前にツールの思想を理解するとよい。 テストをうまく運用するためには、テストの目的を明確にすることが大切。 フロントエンドのテストよりも前に アクセシビリティのガイドラインがあると方針を立てやすい 31