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
テスト自動化ことはじめ(202412_オープンロジ版) / Enter the testing automation (2024 Dec, for OPENLOGI)
tsuemura
0
27
E2Eテストのシナリオと抽象化の粒度の話.pdf
tsuemura
6
540
テスト自動化ことはじめ
tsuemura
3
280
ようこそ、ソフトウェアテストの世界へ!
tsuemura
1
63
コンテキストとセマンティクスを意識してリーダブルなE2Eテストコードを書こう
tsuemura
12
28k
60分で学ぶE2Eテスト(実装編)
tsuemura
0
390
全部乗せフレームワーク CodeceptJS でE2Eテストを楽にしよう
tsuemura
7
5.3k
10年前に初めてVBAで業務自動化したときの思い出
tsuemura
1
14k
テストを自動化するのをやめ、自動テストを作ろう
tsuemura
71
35k
Featured
See All Featured
Building Better People: How to give real-time feedback that sticks.
wjessup
365
19k
Code Reviewing Like a Champion
maltzj
520
39k
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Site-Speed That Sticks
csswizardry
1
180
Producing Creativity
orderedlist
PRO
341
39k
Documentation Writing (for coders)
carmenintech
66
4.5k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
5
430
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
32
2.7k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
How to Think Like a Performance Engineer
csswizardry
21
1.2k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
28
2.1k
Designing on Purpose - Digital PM Summit 2013
jponch
116
7k
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