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
コンテキストとセマンティクスを意識してリーダブルなE2Eテストコードを書こう
Search
tsuemura
July 27, 2022
Technology
12
29k
コンテキストとセマンティクスを意識してリーダブルなE2Eテストコードを書こう
リーダブルなテストコードについて考えよう ~VeriServe Test Automation Talk No.3~ 2022-07-27 での講演スライドです。
tsuemura
July 27, 2022
Tweet
Share
More Decks by tsuemura
See All by tsuemura
自分の軸足を見つけろ
tsuemura
3
1.3k
事業継続を支える自動テストの考え方
tsuemura
0
1.1k
テスト自動化ことはじめ(202412_オープンロジ版) / Enter the testing automation (2024 Dec, for OPENLOGI)
tsuemura
0
1.1k
E2Eテストのシナリオと抽象化の粒度の話.pdf
tsuemura
6
890
テスト自動化ことはじめ
tsuemura
3
440
ようこそ、ソフトウェアテストの世界へ!
tsuemura
1
120
リーダブルなE2Eテストコードのための3つのC
tsuemura
7
1.2k
60分で学ぶE2Eテスト(実装編)
tsuemura
0
430
全部乗せフレームワーク CodeceptJS でE2Eテストを楽にしよう
tsuemura
7
5.5k
Other Decks in Technology
See All in Technology
With Devin -AIの自律とメンバーの自立
kotanin0
2
1k
【CEDEC2025】大規模言語モデルを活用したゲーム内会話パートのスクリプト作成支援への取り組み
cygames
PRO
1
610
隙間時間で爆速開発! Claude Code × Vibe Coding で作るマニュアル自動生成サービス
akitomonam
2
240
마라톤 끝의 단거리 스퍼트: 2025년의 AI
inureyes
PRO
1
430
Strands Agents & Bedrock AgentCoreを1分でおさらい
minorun365
PRO
6
110
私とAWSとの関わりの歩み~意志あるところに道は開けるかも?~
nagisa53
1
150
データ基盤の管理者からGoogle Cloud全体の管理者になっていた話
zozotech
PRO
0
110
AI時代の知識創造 ─GeminiとSECIモデルで読み解く “暗黙知”と創造の境界線
nyagasan
0
180
株式会社島津製作所_研究開発(集団協業と知的生産)の現場を支える、OSS知識基盤システムの導入
akahane92
1
1.3k
AIに全任せしないコーディングとマネジメント思考
kikuchikakeru
0
370
LIFF CLIとngrokを使ったLIFF/LINEミニアプリのお手軽実機確認
diggymo
0
130
AWS re:Inforce 2025 re:Cap Update Pickup & AWS Control Tower の運用における考慮ポイント
htan
1
120
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
530
We Have a Design System, Now What?
morganepeng
53
7.7k
The Straight Up "How To Draw Better" Workshop
denniskardys
235
140k
Code Review Best Practice
trishagee
69
19k
Six Lessons from altMBA
skipperchong
28
3.9k
Making Projects Easy
brettharned
117
6.3k
Done Done
chrislema
185
16k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
A designer walks into a library…
pauljervisheath
207
24k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Transcript
コンテキストとセマンティクスを意識して リーダブルなE2Eテストコードを書こう Takuya Suemura @ Autify, Inc. リーダブルなテストコードについて考えよう ~VeriServe Test
Automation Talk No.3~ 2022-07-27
おれは誰だぜ 末村 拓也 開発者、フィールドエンジニア、QAなどを経て、2019年にAutifyに入社。 自動テスト、特にWebのE2Eテストに強い。 現職ではテクニカルサポートを担当。テスト対象とテストフレームワークの互換性の 問題などを調査、解決する役割を担う。 テトリスが好き。
おれが今まで話してきたこと JaSST'22 Tokyo 60分で学ぶE2Eテスト (ベリサーブ 伊藤由貴さんと共演) https://github.com/tsuemura/jasst22-tokyo JTF2020 テストを自動化するのをやめ、自動テストを作ろう https://speakerdeck.com/tsuemura/tesutowozi-dong-hua-surufalsewoyame-zi-
dong-tesutowozuo-rou 「E2Eテストとはなにか」「理想的なE2Eテストの書き方とは」を ひたすら考えたり話したりし続けている人です
今日話すこと そもそもE2Eテストってどういうものだっけ? E2Eテストをリーダブルにする理由は? どうやってリーダブルにするの?
そもそもE2Eテストとは
よくあるE2Eテストのイメージ ブラウザとかモバイルデバイスを自動操作して WebアプリとかモバイルアプリのUIを ユーザーが操作するのと同じようにテストする
None
(Webの) E2Eテストで用いられる技術 Webブラウザの自動操作技術 Selenium, Cypress, PlayWright etc. 要素特定の手段 CSS Selector,
XPath etc.
E2Eテストの例 Cypressによる擬似コード /** ログインする **/ // メールアドレスを入力 cy.type('input[name=email]', '
[email protected]
') //
パスワードを入力 cy.type('input[name=password]', 'pass1234') // 送信ボタンをクリック cy.click('input[type=submit]') この例では CSSセレクタ で要素を特定し、 それらをクリックしたり、文字を入力したりしている
E2Eテストをリーダブルにする理由は?
E2Eテストをリーダブルにする理由は? =(脳の)メモリの無駄遣いを防ぐ E2Eテストコードは次のようなことを 想像 しながら読まないといけない 長いテストコードを最初から読みながら 今どのページにいるのか想像しながら どのボタンを押しているのか想像しながら 想像をなるべく減らす のがポイント
読みにくいUI操作の例 // 送信ボタン cy.get('button[type="submit"]').click() // 「OK 」ボタン cy.get('button.primary').click() どちらも CSSセレクタ
を用いて要素を探索しているが…… type="submit" が送信ボタンであることを知っているのは エンジニアだけ primary クラスがOKボタンに当たってるのは ただの実装上の都合 ユーザーは type="submit" や .primary のような内部的な属性値を使わず、 ラ ベル で探す 読みにくいだけでなく、ユーザー目線でもないので、誰の得にもならない
読みにくいシナリオの例 // メールアドレスを入力 cy.get('input[name="email"]').type('
[email protected]
') // パスワードを入力 cy.get('input[name="password"]').type('pass1234') // 送信ボタンをクリック cy.get('button[type="submit"]').click()
このページは ログイン ? それとも 新規登録 ?
読みにくいシナリオの例 // 新規登録ページにアクセス cy.visit('/register') // メールアドレスを入力 cy.get('input[name="email"]').type('
[email protected]
') // パスワードを入力 cy.get('input[name="password"]').type('pass1234')
// 送信ボタンをクリック cy.get('button[type="submit"]').click() 直前で「新規登録ページにアクセスした」という 文脈 が無いと読み解けない
ここまでのまとめ 想像で読む部分を減らしたい、そのために ユーザーが要素を探すときと同じ方法で要素を探したい 文脈に依存する書き方を減らしたい
どうやってリーダブルにするの?
どうやってリーダブルにするの? セマンティックな書き方を用いる ユーザーにとって意味のある書き方を用いる コンテキストを明示する 「今何をしているのか」「今どこにいるのか」を明確にする
読みにくいUI操作の例(おさらい) // 送信ボタン cy.get('button[type="submit"]').click() // 「OK 」ボタン cy.get('button.primary').click() どちらも サイトの内部構造
を用いて要素を探索しており ユーザー目線 ではない 意味のある = セマンティックな書き方 を使おう
セマンティックな書き方の例 1. 文言を用いる 2. サイトのアクセシビリティを用いる
1. 文言を用いる Cypress では文言を用いたセレクタを使える 以下の例では Sign Up という文言を含む要素をクリックする cy.contains('Sign Up').click()
※ 複数見つかった場合、一番最初に見つかった要素をクリックしてしまうので注意
文言だけでは出来ないケースはどうしたら? 例: ハンバーガーメニューのアイコン 例: あるラベルを持つ入力フォーム 例: 画像
Testing Library を使ってみよう Testing Library 要素の 役割 や ラベル などを用いてテストコードを書くためのライブラリ
// 例 getByRole("textbox", {name: / メールアドレス/})
Testing Library を使わない場合 // span タグを用いて作成した擬似的な Submit ボタン <span role="button">Submit</span>
// button タグを用いて作成した Submit ボタン <button>Submit</button> この2つは button という role と Submit という name を持つ 意味的にはほぼ等価だが テストフレームワークからは異なるセレクタを使わなければいけない cy.get('span').contain('Submit') cy.get('button').contain('Submit')
Testing Library を使う場合 Testing Library を使うとどちらも同じ形で書ける getByRole("button", {name: /Submit/})
アクセシビリティの高いサイトはテスタビリティも高い Testing Library は アクセシビリティ を用いてテストしている つまり、これら3つがシームレスに実現できる 開発者: アクセシビリティ改善 QA:
アクセシビリティ特性を用いたユーザー目線でのE2Eテスト ユーザー: アクセシビリティの利用 テスターにとってのアクセシビリティの優先度は実は高い テストしにくいサイトがあったときに、 「テストしやすく」ではなく「アクセスしやすく」という提案が出来るかも
どうやって使うの? Testing Library は Cypress, Puppeteer, TestCafe, PlayWrightなど主要なテストフレ ームワークに対応 簡単に試したいならChrome拡張
Testing Playground を使おう
コンテキストを明示する
コンテキストを明示する 読みにくいシナリオの例(おさらい) // メールアドレスを入力 cy.get('input[name="email"]').type('
[email protected]
') // パスワードを入力 cy.get('input[name="password"]').type('pass1234') // 送信ボタンをクリック
cy.get('button[type="submit"]').click() このページは ログイン ? それとも 新規登録 ?
コンテキストを明示する手法 1. Page Object 2. Context Enclosure
Page Object Pattern の利用 ページ内のロケーター、ページ特有の操作などをオブジェクトにまとめるテクニック 本来はメンテナンス性向上のための技だが、副次的にコンテキストを明示することも 出来る const loginPage =
new LoginPage() loginPage.getEmailInput().type('
[email protected]
') loginPage.getPasswordInput().type('pass1234') loginPage.getSubmitButton().click() どのUI要素も loginPage という Page Object のインスタンスから生えている = ログインページ内の要素であることが明示的に示されている
Page Object の実装例 class LoginPage { getEmailInput() { return cy.get('input[name="email"]')
} getPasswordInput() { return cy.get('input[name="password"]') } getSubmitButton() { return cy.get('button[type="submit"]') } } ログインページ内の要素をあらかじめ PageObject 内に定義する
Page Object は結構手間がかかる 例えば、ログインページに Remember me? という チェックボックスを追加したが、Page Objectには追加していないとする const
loginPage = new LoginPage() loginPage.getEmailInput().type('
[email protected]
') loginPage.getPasswordInput().type('pass1234') cy.contains('Remember me?').check() // ここだけ loginPage に属してないように見える loginPage.getSubmitButton().click() 要素を追加した際、かならず Page Object に要素を登録する必要がある Page Object はコンテキストを明示する目的に対しては 重い アプローチ
Context Enclosure 現在のコンテキストに応じてスクリプトの一部を囲う Page Objectよりも「コンテキストを明示する」という意図が明確になる cy.visit("https://demo.realworld.io/#/register"); // 新規登録ページに遷移 // この部分が
Context Enclosure cy.onRegisterPage(cy => { cy.findByPlaceholderText("Username").type("foobar") cy.findByPlaceholderText("Email").type("
[email protected]
") cy.findByPlaceholderText("Password").type("Pass1234") } ※ 名前は先日考えたのでググってもろくなのがでてきません 実装のサンプルは https://zenn.dev/tsuemura/articles/13b0ea44c1a20a
Context Enclosure の実装方法 Cypress.Commands.add("onRegisterPage", (fn) => { fn(cy); }); 1ページにつき3行で実装でき軽量
Cypressの場合はカスタムコマンドで実装する
コンテキスト内でのみ利用できるコマンド Cypress.Commands.add("onRegisterPage", (fn) => { Cypress.Command.Add("showMessage", (message) => { //
独自コマンドの定義 cy.log(message) }) cy.url().should('include', 'register') // register ページにいることを確認 fn(cy); }); onRegisterPage の中でだけ利用できる showMessage というコマンドを定義し た 例えば login や fillCredentials のようなhelperを定義してあげるとテストコ ード記述が楽になる 同時に onRegisterPage が呼ばれた段階で register を含むURLにいることを確 認している
Context Enclosure の利点 最低限の実装であれば各ページ3行ぐらいで済むので楽 全てのページに実装するのもそう大変ではない 「あるコンテキストにいる」という検証をセットで実装できる コンテキストに応じて独自のコマンドを実装できる Context Enclosure の欠点
こないだ考えたばっかりなのであんまり枯れたアイディアではないこと
今日ほとんど Context Enclosure の話をしに来たんで フィードバックもらえると助かります
まとめ
まとめ 悩まずにテストコードを読み書きするためにリーダビリティに気を使う そのためにセマンティクス(≒ アクセシビリティ)とコンテキストの2つを紹介した ユーザー目線で、文脈が明確なテストコードを書こう
Enjoy Testing! スライドか?欲しけりゃくれてやるぜ…… 探してみろ 今日の発表資料の全てをSpeakerdeckに置いてきた (Twitter / Zoomのチャットとかでも共有されると思います)