Slide 1

Slide 1 text

AI powered Quality Engineering Platform 2024.06.20 「テスト⾃動化実践ガイド」著者直伝! 読みやすいE2Eテストコードの書き⽅ 末村 拓也 Developer Summit 2024 KANSAI 2024.9.18 AI powered Quality Engineering Platform #devsumi #devsumiB

Slide 2

Slide 2 text

末村 拓也 - Quality Evangelist at Autify - 倉庫内軽作業→Web開発者→QAエンジニ ア→テクニカルサポート→マーケター - 品質・テスト周りの議論が好き 自己紹介 #devsumi #devsumiB

Slide 3

Slide 3 text

テスト自動化実践ガイド - テストって何なん - どうやるん というような話を350ページで長々と説明 本が出ました #devsumi #devsumiB

Slide 4

Slide 4 text

書籍の中でも特に反響の大きかった 第2部第9章「テストコードに意図を込める」 を解説 今日話すこと #devsumi #devsumiB

Slide 5

Slide 5 text

コメントに頼らず、テストコード自身が十分 説明的 である ● コンテキスト(文脈)を明示する ● 状態を表す ● セマンティクスを明示する 「意図を込める」とは #devsumi #devsumiB

Slide 6

Slide 6 text

コンテキストを明示する #devsumi #devsumiB

Slide 7

Slide 7 text

コンテキストを明示する 管理者 - 「商品追加」をクリック 一般 - 「Tシャツ」をカートに入れる - 「カートを見る」をクリック 商品追加画面 - 商品名「Tシャツ」を入力 - 「追加」をクリック カート画面 - 「2,200円」と表示されていることを確認 - 「購入」をクリック #devsumi #devsumiB

Slide 8

Slide 8 text

// 店舗スタッフとしてログインする I.amOnPage("/"); I.click("ログインする"); I.fillField("ユーザー名", "admin"); I.fillField("パスワード", "amin"); I.click("ログイン") // この後の処理は、暗黙に「店舗スタッフとしてログイン後」を期待されている I.click("スタッフ用マイページ") コンテキストを明示する (1) ログイン状態 #devsumi #devsumiB

Slide 9

Slide 9 text

I.amStoreStaff( (I) => { // ... ここに店舗スタッフとして実行したい処理を書く I.click("スタッフ用マイページ") }) コンテキストを明示する (1) ログイン状態 #devsumi #devsumiB

Slide 10

Slide 10 text

// ここから商品一覧ページ I.amOnPage("/items"); const itemContainer = locate("tr").withText("トマト") I.click("商品を編集", itemContainer); // ここから商品編集ページ I.fillField("商品名", "プチトマト"); I.click("変更"); // ここまで商品編集ページ // ここから商品一覧ページ コンテキストを明示する (2) ページ遷移 #devsumi #devsumiB

Slide 11

Slide 11 text

I.shouldBeOnItemListPage(I => { const itemContainer = locate('tr').withText("トマト") I.click("商品を編集", itemContainer(itemName)); I.shouldBeOnItemDetailPage(I => { I.fillField("商品名", "プチトマト"); I.click("変更"); }) }) コンテキストを明示する (2) ページ遷移 #devsumi #devsumiB

Slide 12

Slide 12 text

状態を表す #devsumi #devsumiB

Slide 13

Slide 13 text

E2Eテストはあらゆるものを手続き的に書けて「しまう」 ● テストデータの準備 ● 前提条件 ● 事後条件 ● 実行後処理 これらは手続きではなく、満たすべき状態 状態を表す #devsumi #devsumiB

Slide 14

Slide 14 text

// テスト用の商品を追加する I.click("商品を追加する"); const itemName = `牛ハラミ弁当-テス ト-${utils.now.format("YYYYMMDDHHmmss")}`; I.fillField("商品名", itemName); I.fillField("商品説明", "テスト用の商品です"); I.fillField("価格", "500"); I.click("追加"); 状態を表す - 手続き的に書かれたデータ準備の例 #devsumi #devsumiB

Slide 15

Slide 15 text

// テスト用の商品があるという前提条件が重要であり、手順はどうでもいい const itemName = await I.haveItem() 状態を表す - 「〜を持っている」という状態を表現する #devsumi #devsumiB

Slide 16

Slide 16 text

内部的には冪等性(何度実行しても同じ状態になる性質)に気をつける ● 冪等なAPIを叩いてデータを作成する ● 毎回ユニークな名前のデータを作る 状態を表す - 実装 #devsumi #devsumiB

Slide 17

Slide 17 text

セマンティクスを明示する #devsumi #devsumiB

Slide 18

Slide 18 text

セマンティクス = 要素が持つ 意味 テスト対象の内部属性ではなく、文言などのアクセシブルな属性を用いる ❌ 内部属性 ● id ● class セマンティクスを意識する #devsumi #devsumiB ⭕ アクセシブルな属性 ● 文言 ● altテキスト ● aria-role

Slide 19

Slide 19 text

// CodeceptJSは標準で文言のみで要素探索できる I.fillField("注文数", "10"); I.click("送信"); // Playwrightなどでは getByRole などを中心に使う await page.getByLabel('注文数').fill('10'); await page.getByRole('button', { name: '送信' }).click(); セマンティクスを意識したロケーター #devsumi #devsumiB

Slide 20

Slide 20 text

まとめ ● 手順が連続する状況では コンテキスト を明示する ● 前提条件の準備手順は テストコードから隠蔽して 状態 だけを表すようにする ● セマンティクス を意識したロケーターで ユーザー目線で意味のある テストコードにする #devsumi #devsumiB

Slide 21

Slide 21 text

Enjoy Testing! おわり #devsumi #devsumiB