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テストコードのための3つのC
Search
tsuemura
August 08, 2024
7
1k
リーダブルなE2Eテストコードのための3つのC
Playwright本出版記念!Node学園 43時限目 2024-08-08
https://nodejs.connpass.com/event/325813/
tsuemura
August 08, 2024
Tweet
Share
More Decks by tsuemura
See All by tsuemura
E2Eテストのシナリオと抽象化の粒度の話.pdf
tsuemura
6
500
テスト自動化ことはじめ
tsuemura
3
250
ようこそ、ソフトウェアテストの世界へ!
tsuemura
1
59
コンテキストとセマンティクスを意識してリーダブルなE2Eテストコードを書こう
tsuemura
12
28k
60分で学ぶE2Eテスト(実装編)
tsuemura
0
380
全部乗せフレームワーク CodeceptJS でE2Eテストを楽にしよう
tsuemura
7
5.2k
10年前に初めてVBAで業務自動化したときの思い出
tsuemura
1
14k
テストを自動化するのをやめ、自動テストを作ろう
tsuemura
71
34k
How can we improve the testability of applications?
tsuemura
0
960
Featured
See All Featured
It's Worth the Effort
3n
183
27k
4 Signs Your Business is Dying
shpigford
180
21k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
Speed Design
sergeychernyshev
24
610
A designer walks into a library…
pauljervisheath
202
24k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
1.8k
YesSQL, Process and Tooling at Scale
rocio
168
14k
A Modern Web Designer's Workflow
chriscoyier
693
190k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
Fireside Chat
paigeccino
33
3k
Into the Great Unknown - MozCon
thekraken
32
1.5k
Unsuck your backbone
ammeep
668
57k
Transcript
リーダブルな E2Eテストコードのための 3つの C Takuya Suemura 2024-08-08 Playwright本出版記念! Node学園 43時限目
1
自己紹介 末村 拓也 プロフィール写真を 37年間更新し忘れている Quality Evangelist at Autify エンジニアですが、マーケティングチームに異
動しました(今日) テトリスとキーボードが好きです 2
宣伝だ テスト自動化実践ガイド CodeceptJS + Playwright の組み合わせ で E2Eテストを書く テスト自動化を始める前から運用まで広 くカバー
ハンズオンのためにゴミみたいなアプリ を頑張って作りました ゴミみたいなアプリに自動テストを 書かないといけない場合に便利 3
CodeceptJS って何 WebDriverや Playwright などをラップして単一の APIを提供する 一人称の I から始まる 自然な英文法のシンタッ
クス I click something I see something 4
その他執筆・登壇 ORDER BY LIKES 我が名は神龍 ……どんなテストもひとつだけ自動化してやろう (Qiita, 2018) クロスブラウザテストの闇と闇と闇 (D-CUBE,
2019) テストを自動化するのをやめ、自動テストを作ろう (July Tech Festa, 2020) etc 5
今日話すこと E2Eテストの認知負荷の話 認知負荷を下げる 3つの C Context Capability Component これらを CodeceptJSや
Playwrightでどう表現するか 説明は CodeceptJSでやりますが Playwrightでもできます(たぶん) 書籍ではハンズオンパートの最後に説明があります 3つの Cという言葉は出版後に思いついたので今回が初出です 6
認知負荷 (Cognitive Load) とは コードリーディングを妨げる「覚えておかないといけない」 「想像しないといけない」こと クソデカスコープ変数 クソデカ依存関数 何の意味があるのか分からない処理 7
E2Eテストの認知負荷 どこのページにいるのか、どのユーザーでログインしているのか いまやっているのはテストなのか準備なのか 何を操作しようとしているのか E2Eテストは何も考えずに書くとゴリゴリの手続き型プログラミングになるので こういうところをケアしながら書いてあげたい 8
認知負荷を下げる工夫 「あるページにいる」 「あるユーザーでログインしている」という 状況 (Context) を表 現する 「何が出来るべきなのか」という 能力 (Capability)
を表現する 「何を操作しようとしているのか」という 部品 (Component) を表現する 9
Context 状況を表現する 10
Context(状況) いま、どのページにいるのか いま、どのユーザーでログインしているのか etc 11
ある ECサイトのテストコード I.click('購入に進む') // 商品購入画面へ遷移 I.click('決済方法を選択') '購入に進む ' をクリックすると画面遷移が期待されているが、 コードでは表されていない状態
ページ遷移に失敗すると、 決済方法を選択 要素が存在せずエラーになるが、 欲を言うと 期待したページに遷移していない エラーで失敗してほしい 12
Contextをコードで表現する I.click('購入に進む') I.shouldBeOnPurchasePage(I => { I.click('決済方法を選択') }) 13
実装はシンプル shouldBeOnPurchasePage(fn) { I.seeInUrl('/purchase') fn(I) } 14
その他の使い道 : ログイン状態を表現する amStoreStaff(fn) { const I = actor({}); session('StoreStaff',
() => { I.amOnPage("/"); I.click("ログインする"); I.fillField("ユーザー名", "admin"); I.fillField("パスワード", "admin"); I.click("ログイン"); fn(I) }) }, amAnonimousUser(fn) { const I = actor({}); session('AnonimousUser', () => { fn(I) }) } 15
Capability (前提条件として)何が出来るべきか 16
ある ECサイトのテストデータ準備コード const itemName = `牛ハラミ弁当-テスト-${utils.now.format("YYYYMMDDHHmmss")}`; I.amOnPage('/items/add') I.seeInTitle('商品追加') I.fillField("商品名", itemName);
I.fillField("商品説明", "テスト用の商品です"); I.fillField("価格", "500"); I.fillField("在庫数", "10") I.click("追加"); 17
I.canPurchaseItem テストデータが準備されている状態が重要なので、手順は隠蔽する I can purchase item (商品を購入できる)という前提条件として記述する const itemName =
`テスト商品-${Date.now()}` I.canPurchaseItem(itemName) // 商品を購入する I.click(itemName) 18
canPurchaseItem の実装例 canPurchaseItem: (name) { const I = actor({}); if
(!name) name = `牛ハラミ弁当-テスト-${utils.now.format("YYYYMMDDHHmmss")}`; I.amOnPage('/items/add') I.seeInTitle('商品追加') I.fillField("商品名", name); I.fillField("商品説明", "テスト用の商品です"); I.fillField("価格", "500"); I.click("追加"); I.see(name) return name; } 19
Component ページ内のコンポーネントを抽象化する 20
UIコンポーネントを抽象化する <h3> ハムエッグの材料 </h3> <table> <tr> <th> 卵 </th> <td>
1個 </td> <td><button>購入</button></td> </tr> <tr> <th> ハム </th> <td> 2枚 </td> <td><button>購入</button></td> </tr> </table> const row(header) { return locate('tr').withChild( locate('th').withText(header) ) } 21
<h3> ハムエッグの材料 </h3> <table> <tr> <th> 卵 </th> <td> 1個
</td> <td><button>購入</button></td> </tr> <tr> <th> ハム </th> <td> 2枚 </td> <td><button>購入</button></td> </tr> </table> within(row('ハム'), () => { I.click('購入') }) 22
アンチパターン : 操作と要素探索をまとめてしまう I.purchaseHam() I.purchaseEgg() purchase ("購入 " ボタンのクリック )
と Ham/Egg (購入する商品)をまとめたメソッドを作っている 中で何をしているのかが分からなくなる 項目の数だけメソッドを定義しなければならなくなる 23
まとめ E2Eテストの認知負荷を下げるには "3つの C" を理解しよう Context(状況) Capability(能力≒前提条件) Component(部品) ユーザー目線で抽象化していくことで、コメントに頼らずテストコードが書ける CodeceptJSはいいぞ(今日何の会だっけ?)
24
Enjoy Testing! 25