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
260
フロントエンドの単体テストの使い方/考え方
Tomoya Kashifuku
March 16, 2023
Tweet
Share
More Decks by Tomoya Kashifuku
See All by Tomoya Kashifuku
Rustでオリジナルnpmパッケージを作ってみよう
tnyo43
0
100
ユーザのためだけじゃない!エンジニアも嬉しいアクセシビリティ改善のための自動テスト
tnyo43
0
340
ルールの運用から始めるフロントエンド開発改善
tnyo43
5
2.7k
Elm でつくるルービックキューブ
tnyo43
1
410
Other Decks in Programming
See All in Programming
Pinia Colada が実現するスマートな非同期処理
naokihaba
4
220
受け取る人から提供する人になるということ
little_rubyist
0
230
GitHub Actionsのキャッシュと手を挙げることの大切さとそれに必要なこと
satoshi256kbyte
5
430
Jakarta Concurrencyによる並行処理プログラミングの始め方 (JJUG CCC 2024 Fall)
tnagao7
1
290
Make Impossible States Impossibleを 意識してReactのPropsを設計しよう
ikumatadokoro
0
170
どうして僕の作ったクラスが手続き型と言われなきゃいけないんですか
akikogoto
1
120
Creating a Free Video Ad Network on the Edge
mizoguchicoji
0
120
シールドクラスをはじめよう / Getting Started with Sealed Classes
mackey0225
4
640
Ethereum_.pdf
nekomatu
0
460
Amazon Bedrock Agentsを用いてアプリ開発してみた!
har1101
0
330
OnlineTestConf: Test Automation Friend or Foe
maaretp
0
110
NSOutlineView何もわからん:( 前編 / I Don't Understand About NSOutlineView :( Pt. 1
usagimaru
0
330
Featured
See All Featured
Teambox: Starting and Learning
jrom
133
8.8k
Making Projects Easy
brettharned
115
5.9k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
93
16k
Docker and Python
trallard
40
3.1k
Statistics for Hackers
jakevdp
796
220k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Speed Design
sergeychernyshev
24
610
10 Git Anti Patterns You Should be Aware of
lemiorhan
654
59k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
YesSQL, Process and Tooling at Scale
rocio
169
14k
4 Signs Your Business is Dying
shpigford
180
21k
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