Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Webフロントエンドのための実践「テスト」手法 CodeZine Night #1

Webフロントエンドのための実践「テスト」手法 CodeZine Night #1

CodeZine編集部主催のウェビナー「CodeZine Night」の第一回発表資料
https://codezine.connpass.com/event/279012

Takepepe

May 10, 2023
Tweet

More Decks by Takepepe

Other Decks in Programming

Transcript

  1. Web フロントエンドのための
    実践「テスト」手法
    CodeZine Night #1 @ Takepepe

    View full-size slide

  2. 自己紹介
    ■ Takepepe(吉井 健文)
    ■ 社内横断開発組織に所属
    ■ フロントエンド開発の横断サポート

    View full-size slide

  3. 【投票】「フロントエンド開発のためのテスト入門」は、もう読まれましたか?
    フロントエンド開発のためのテスト入門
    ■ 2023.4/24 翔泳社より刊行
    ■ フロントエンド開発におけるテスト手法を紹介
    ■ 単体テストからE2Eテストまでを体系的に
    ■ 自動テストがはじめてという方にも

    View full-size slide

  4. Agenda
    ■ 第1章:フロントエンドテストを書く目的
    ■ 第2章:a11y の当たり前品質
    ■ 第3章:テストがない状況からの脱却
    本日は、書籍で紹介しきれなかった内容が中心です

    View full-size slide

  5. 第1章
    フロントエンドテストを書く目的

    View full-size slide

  6. 第1章:フロントエンドテストを書く目的
    テスト、書いていますか?
    【投票】フロントエンドの自動テストを導入して「良かった」と思ったことはありますか?
    ■ なんとなく今後の運用が「不安」である
    ■ バックログに積みっぱなしの「テストを書く」というチケット
    ■ いつまでたっても優先度があがらない

    View full-size slide

  7. 第1章:フロントエンドテストを書く目的
    テストの目的は何か?
    ■ 目的はサービスの「品質」を保ち続けること
    ■ 自動テストは「品質」を担保してくれる
    ■ 自動テストを書くことで「品質」があがる
    そもそも期待している「品質」って何だっけ?

    View full-size slide

  8. 第1章:フロントエンドテストを書く目的
    テストに求める「品質」の定義
    ■ 狩野モデルによると、品質は5つに分類される
    当たり前品質 支障なくサービスが利用できること
    一元的品質 充足するとプラス評価、不充足はマイナス評価となるもの
    魅力的品質 競合にない付加価値で、プラス評価となるもの
    無関心品質 顧客の評価に影響しない、サービス提供側都合の品質
    逆品質 存在することで、サービスのマイナス評価となるもの

    View full-size slide

  9. 第1章:フロントエンドテストを書く目的
    テストに求める「品質」の定義
    ■ フロントエンド開発対象「UI」に置き換えると…
    当たり前品質 ボタンが押せて、画面遷移できる(欠陥がない)
    一元的品質 画面がサクサク遷移し、レスポンスが良い(非機能面が優良)
    魅力的品質 競合にない UI で、作業効率化のために欠かせない(差別化)
    無関心品質 顧客の評価に影響しない、サービス提供側都合の品質
    逆品質 存在することで、サービスのマイナス評価となるもの

    View full-size slide

  10. 第1章:フロントエンドテストを書く目的
    フロントエンド開発の自動テストスコープ
    ■ 機能テスト(リグレッションテスト)
    日常的な開発で、故障に気づけるように
    当たり前品質 一元的品質 魅力的品質
    利用者 ✅ ー ー
    ??? ー ー ー

    View full-size slide

  11. 第1章:フロントエンドテストを書く目的
    フロントエンド開発の自動テストスコープ
    ■ 非機能テスト(パフォーマンステスト・アクセシビリティテスト等)
    非機能要件追求は「コストと相談のうえ」という実態
    当たり前品質 一元的品質 魅力的品質
    利用者 ✅ ✅ ー
    ??? ー ー ー

    View full-size slide

  12. 第1章:フロントエンドテストを書く目的
    フロントエンド開発の自動テストスコープ
    ■ Web アクセシビリティに対する関心の高まり
    支援技術利用者目線でも、品質を向上しよう
    当たり前品質 一元的品質 魅力的品質
    利用者 (障害無し) ✅ ✅ ー
    利用者 (障害有り) ❌ ❌ ー

    View full-size slide

  13. 第1章:フロントエンドテストを書く目的
    フロントエンド開発の自動テストスコープ
    ■ Web アクセシビリティに対する関心の高まり
    【投票】普段 Web アクセシビリティを考慮できていますか?
    当たり前品質 一元的品質 魅力的品質
    利用者 (障害無し) ✅ ✅ ー
    利用者 (障害有り) ❌ ❌ ー

    View full-size slide

  14. 第1章:フロントエンドテストを書く目的
    フロントエンド開発の自動テストスコープ
    ■ フロントエンドテストツールでいま
    注力されているもの
    当たり前品質 一元的品質 魅力的品質
    利用者 (障害無し) ✅ ✅ ー
    利用者 (障害有り) ❌ ❌ ー
    Web アクセシビリティにも「当たり前品質」を

    View full-size slide

  15. 第1章:フロントエンドテストを書く目的
    ■ Testing Library の狙い
    ー アクセシビリティ由来のクエリー(セマンティッククエリー)
    ー 機能テストを書くと、a11y の「当たり前品質」を意識することに
    ー a11y の欠陥に、日常的に気づける
    フロントエンドテストツールの変化
    Queries Accessible to Everyone: https://testing-library.com/docs/queries/about#priority

    View full-size slide

  16. 第1章:フロントエンドテストを書く目的
    ■ Playwright も追従
    ー v.1.27.0 で、Locator に新機能(書籍執筆中に発生)
    ー getByRole など、Testing Library にインスパイアされた API
    ー 公式として、この Locator を使用したコードを推奨
    フロントエンドテストツールの変化
    New APIs, inspired by Testing Library: https://github.com/microsoft/playwright/releases/tag/v1.27.0

    View full-size slide

  17. 第2章
    a11y の当たり前品質

    View full-size slide

  18. 第2章:a11y の当たり前品質
    a11y の「当たり前品質」とは?
    ■ リンクを押下すると画面遷移できるか
    ■ フォームが送信できるか
    ■ ドキュメントが意図どおり提供できているか
    ー 文章構造、CSS、a11y tree

    View full-size slide

  19. 第2章:a11y の当たり前品質
    a11y tree とは?
    ■ アクションを実行できるアクセシビリティオブジェクトのツリー
    ■ DOMツリーから派生したもの
    ■ 支援技術が属性とプロパティを照会
    ■ 支援技術にドキュメントがどう見えているか示すツリー

    View full-size slide

  20. 第2章:a11y の当たり前品質
    Full accessibility tree とは?
    ■ Google Chrome の 実験的な機能
    ■ Elements パネルから確認でき、日常のデバッグに便利
    ■ Storybook では、UI コンポーネント単位でツリーが確認できる
    Full accessibility tree in Chrome DevTools: https://developer.chrome.com/blog/full-accessibility-tree

    View full-size slide

  21. 第2章:a11y の当たり前品質

    View full-size slide

  22. 第2章:a11y の当たり前品質

    View full-size slide

  23. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例1:リンクにクリックログを仕込む
    ー onClick イベントにログ送信処理を追加
    ー 画面遷移前にログを送信できている
    ー 画面遷移もきちんと出来ている
    ー 自動テストが失敗。原因は何だったか?
    参考PR:https://github.com/frontend-testing-book/unittest/pull/5

    View full-size slide

  24. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例1:リンクにクリックログを仕込む
    ー onClick イベントにログ送信処理を追加
    ー 画面遷移前にログを送信できている
    ー 画面遷移もきちんと出来ている
    ー 自動テストが失敗。原因は何だったか?
    href 属性がなくなった影響で「 link」ロールが欠落 → 支援技術利用者は画面遷移できない

    View full-size slide

  25. 第2章:a11y の当たり前品質
    ■ 事例2:独自デザインのチェックボックスを実装する
    ー チェックボックスコンポーネントに状態を保持
    ー 状態に応じてデザインを切り替えて
    ー チェックができ、状態が参照できている
    ー 自動テストが失敗。原因は何だったか?
    参考PR:https://github.com/frontend-testing-book/unittest/pull/3
    a11y 欠陥の具体例

    View full-size slide

  26. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例2:独自デザインのチェックボックスを実装する
    ー チェックボックスコンポーネントに状態を保持
    ー 状態に応じてデザインを切り替えて
    ー チェックができ、状態が参照できている
    ー 自動テストが失敗。原因は何だったか?
     display: none; 指定による a11y tree からの除外 → 支援技術利用者は操作継続できない

    View full-size slide

  27. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例2:独自デザインのチェックボックスを実装する
    ー チェックボックスコンポーネントに状態を保持
    ー 状態に応じてデザインを切り替えて
    ー チェックができ、状態が参照できている
    ー 自動テストが失敗。原因は何だったか?
    a11y tree の算出は CSS も関係する → jsdom のテストでは不十分な場合がある

    View full-size slide

  28. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例2:独自デザインのチェックボックスを実装する
    ー チェックボックスコンポーネントに状態を保持
    ー 状態に応じてデザインを切り替えて
    ー チェックができ、状態が参照できている
    ー 自動テストが失敗。原因は何だったか?
    jsdom のテストでは不十分な場合 → CSS Modules をモックしている場合など

    View full-size slide

  29. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例3:デザインを調整する例
    ー デザインシステムを導入した
    ー デザイントークンを使用し、見出しに統一をもたせた
    ー デザインデータ通りの実装になった
    ー 自動テストが失敗。原因は何だったか?
    参考PR:https://github.com/frontend-testing-book/nextjs/pull/5

    View full-size slide

  30. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例3:デザインを調整する例
    ー デザインシステムを導入した
    ー デザイントークンを使用し、見出しに統一をもたせた
    ー デザインデータ通りの実装になった
    ー 自動テストが失敗。原因は何だったか?
    コントラスト比が不十分 → 色覚障害のある利用者に見えない

    View full-size slide

  31. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    axe-playwright を使用した、Story 毎のアクセシビリティ違反チェック
    ■ 事例3:デザインを調整する例
    await checkA11y(page, "#root", {
    includedImpacts: ["critical", "serious"],
    detailedReport: false,
    detailedReportOptions: { html: true },
    axeOptions: storyContext.parameters?.a11y?.options,
    });

    View full-size slide

  32. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    "critical", "serious", "moderate", "minor" の検証レベル指定(コントラスト比は "serious")
    ■ 事例3:デザインを調整する例
    await checkA11y(page, "#root", {
    includedImpacts: ["critical", "serious"],
    detailedReport: false,
    detailedReportOptions: { html: true },
    axeOptions: storyContext.parameters?.a11y?.options,
    });

    View full-size slide

  33. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    ■ 事例4:E2E テストで見つかった a11y 欠陥
    ー Storybook では a11y 違反は検出されなかった
    ー 自動テストが失敗。原因は何だったか?
    参考PR:https://github.com/frontend-testing-book/nextjs/pull/6

    View full-size slide

  34. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    axe-playwright を使用した、ページ毎のアクセシビリティ違反チェック
    ■ 事例4:E2E テストで見つかった a11y 欠陥
    test("アクセシビリティ検証 ", async ({ page }) => {
    await page.goto(url(path));
    await injectAxe(page);
    await checkA11y(page);
    });

    View full-size slide

  35. 第2章:a11y の当たり前品質
    a11y 欠陥の具体例
    a11y 欠陥は E2E テスト時に発覚することも
    ■ 事例4:E2E テストで見つかった a11y 欠陥
    test("アクセシビリティ検証 ", async ({ page }) => {
    await page.goto(url(path));
    await injectAxe(page);
    await checkA11y(page);
    });

    View full-size slide

  36. 第2章:a11y の当たり前品質
    axe について
    ■ Web アクセシビリティのための自動テストツール
    ー ブラウザで利用する a11y 検証ツール(ブラウザ固有のテスト)
    ー Testing Library は DOM から算出した a11y tree 検証にとどまる
    ー Storybook test runner でしか検出できない欠陥 → コントラスト比等
    ー ブラウザE2Eテストフレームワークでしか検出できない欠陥
    ブラウザで実行されるため、忠実性の高い a11y 検証ができる

    View full-size slide

  37. 第2章:a11y の当たり前品質
    a11y とテスト、どう向き合うか
    ■ ARIA の誤用に気をつけよう
    ー テストのための符号として ARIA 属性を付与しがち
    ー テスト・デバッグツールの解釈と、支援技術には差がある
    ー テストついでに a11y 改善を行う場合、正しい用法か確認を
    ー テストで要素取得できているからといってアクセシブルとは限らない
    No ARIA is better than Bad ARIA:https://www.w3.org/WAI/ARIA/apg/practices/read-me-first

    View full-size slide

  38. 第2章:a11y の当たり前品質
    a11y とテスト、どう向き合うか
    ■ 自動テストを書く日常の一環として
    ー a11y の「当たり前品質」を担保するリグレッションテストとして
    ー できれば UI コンポーネント作成段階で a11y 品質を考慮しよう
    ー できれば支援技術(スクリーンリーダーなど)で確認を
    ー まず自動テストを書く事が目的なら、
    data-testid 属性から始めて良い
    自動テストで、アクセシビリティの「当たり前品質」を担保

    View full-size slide

  39. 第3章
    テストがない状況からの脱却

    View full-size slide

  40. 第3章:テストがない状況からの脱却
    フロントエンド品質に a11y が関連するのは理解したけれど…
    ■ フロントエンドテストを書く動機
    ー リファクタリングしたいけれど、大丈夫
    …?
    ー ライブラリをアップデートしたいけれど、大丈夫
    …?
    ー 新機能の追加、既存機能に影響でていない
    …?

    View full-size slide

  41. 第3章:テストがない状況からの脱却
    フロントエンド品質に a11y が関連するのは理解したけれど…
    ■ フロントエンドテストを書く動機
    ー a11y 考慮が十分じゃないとテストは書けない? → No
    ー 最低限の「当たり前品質」を担保することが目的
    気負わず出来るところから着手しよう

    View full-size slide

  42. 第3章:テストがない状況からの脱却
    フロントエンドテストを導入したいけれど…
    ■ 現場に障壁があって…
    ー 運用コスト・学習コストが高い
    ー テストを書く時間がない
    ー テストを書く文化がない
    【投票】自動テスト導入の一番の障壁は何ですか?

    View full-size slide

  43. 第3章:テストがない状況からの脱却
    テストがない状況における目的
    ■ 最低限の「当たり前品質」担保
    当たり前品質 一元的品質 魅力的品質
    利用者 (障害無し) ❌ ー ー
    利用者 (障害有り) ー ー ー
    これを最短距離で達成するテストは何か?

    View full-size slide

  44. 第3章:テストがない状況からの脱却
    テストツールの守備範囲
    ■ テストツールには得意・不得意がある
    ✅:優良(詳細・速い)/  🟠:守備範囲 / ❌:守備範囲外
    snapshot (DOM) 機能テスト VRT axe (a11y) E2E
    jsdom + RTL ✅ ✅ ❌ ❌ ❌
    Storybook 🟠 🟠 ✅ ✅ ❌
    Playwright ❌ 🟠 🟠 🟠 🟠

    View full-size slide

  45. 第3章:テストがない状況からの脱却
    テストツールの守備範囲
    ■ Story はテストケースとして import し、jsdom で検証できる
    composeStories は Storybook v7 に標準機能として統合
    snapshot (DOM) 機能テスト VRT axe (a11y) E2E
    jsdom + RTL ✅ ✅ ❌ ❌ ❌
    Storybook ✅ ✅ ✅ ✅ ❌
    Playwright ❌ 🟠 🟠 🟠 🟠
    import import

    View full-size slide

  46. 第3章:テストがない状況からの脱却
    はじめの自動テストとして
    ■  Storybook をお薦めする理由
    ー  jsdom のテストケースとして Story を再利用 (composeStories)
    ー VRT (ビジュアルリグレッションテスト) や axe (a11y ) も
    ー テスト対象が細分化されているめ、欠陥を突き止めやすい
    ー テストケースの状態 (UI) が目視で確認できる
    ー MSW も使える
    その時のニーズにあわせて取捨選択できる

    View full-size slide

  47. 第3章:テストがない状況からの脱却
    MSW って何だっけ?
    ■ Mock Service Worker
    ー モックサーバー(HTTP リクエストをインターセプトできる)
    ー UI コンポーネントに必要な、データ取得・更新 API を再現
    ー Jest だけでなく、Web API 依存の Story が表現できる
    ー 例えば 「Web API 取得失敗した場合表示はこうなる」という Story
    MSW Storybook Addon:https://storybook.js.org/addons/msw-storybook-addon

    View full-size slide

  48. 第3章:テストがない状況からの脱却
    MSW って何だっけ?
    ■ Mock Service Worker
    ー モックサーバー(HTTP リクエストをインターセプトできる)
    ー UI コンポーネントに必要な、データ取得・更新 API を再現
    ー Jest だけでなく、Web API 依存の Story が表現できる
    ー 例えば 「Web API 取得失敗した場合表示はこうなる」という Story
    MSW を使った技術記事をいくつか投稿しています :https://zenn.dev/takepepe

    View full-size slide

  49. 第3章:テストがない状況からの脱却
    段階的に自動テストを導入しよう
    ■ 自動テスト拡充のロードマップ(例)
    ー 1)ページ相当のコンポーネントを Story 登録
    ー 2)MSW Storybook Addon を活用し、ページの Story を複数登録
    ー 3)Storybook Play function を活用し、機能テストを追加する
    ー 4)Storybook Test runner が CI で実行されるよう設定
    この段階で VRT(ビジュアルリグレッションテスト)があると尚良い

    View full-size slide

  50. 第3章:テストがない状況からの脱却
    段階的に自動テストを導入しよう
    ■ 自動テスト拡充のロードマップ(例)
    リファクタリングに取り組める状態になった
    当たり前品質 一元的品質 魅力的品質
    利用者 (障害無し) ✅ ー ー
    利用者 (障害有り) ❌ ー ー

    View full-size slide

  51. 第3章:テストがない状況からの脱却
    段階的に自動テストを導入しよう
    ■ 自動テスト拡充のロードマップ(例)
    ー 5)コンポーネントを細分化していく
    ー 6)コンポーネントから処理を切り出す(関数・
    Hooks)
    ー 7)切り出した処理の単体テストを拡充する
    ー 8)切り出したコンポーネントの a11y を当たり前品質に
    「リファクタリング -> a11y 改善」を段階的に進める

    View full-size slide

  52. 第3章:テストがない状況からの脱却
    段階的に自動テストを導入しよう
    ■ 自動テスト拡充のロードマップ(例)
    自動テスト導入を機に「 a11y の当たり前品質」も満たしていきましょう
    当たり前品質 一元的品質 魅力的品質
    利用者 (障害無し) ✅ ー ー
    利用者 (障害有り) ✅ ー ー

    View full-size slide

  53. ご清聴ありがとうございました

    View full-size slide