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
AIのためのテスト戦略 〜TDDが難しいフロントエンド開発でのアプローチ〜
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Hayato Yokoyama
October 04, 2025
Technology
250
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AIのためのテスト戦略 〜TDDが難しいフロントエンド開発でのアプローチ〜
Hayato Yokoyama
October 04, 2025
More Decks by Hayato Yokoyama
See All by Hayato Yokoyama
「型ガードしたのにnullable」から卒業する
hayato_yokoyama
0
110
「バイトル」のTypeScriptリニューアル — 積み上がったレガシーとパフォーマンスに挑む現在地
hayato_yokoyama
0
26
AIが特別じゃなくなった時代に、作ることを楽しもう
hayato_yokoyama
0
27
実はすごいスピードで進化しているCSS
hayato_yokoyama
0
240
Next.js AppRouter × GraphQL 〜 夢見た理想と現実の課題 〜
hayato_yokoyama
0
170
フロントエンドテストを書きやすくするために工夫したこと
hayato_yokoyama
1
89
Other Decks in Technology
See All in Technology
千葉での単身赴任からAWSをやり続け、千葉に戻ってきた話
yama3133
1
100
OTel × Datadog で 「AI活用」を計測し、改善に繋げる
shihochan
2
540
サイバーエージェントにおけるAI推進戦略と変革への取り組み
shotatsuge
0
360
SONiCの統計情報を取得したい
sonic
0
270
[チョークトーク資料]AWS DevOps Agent を使いこなす / AWS Dev Ops Agent Chalk Talk AWS Summit Japan 2026
kinunori
3
710
【Cyber-sec+】経営層を"動かす"ための考え方
hssh2_bin
0
200
「軸足」は 固定しなくていい - 熱量と強みで描く、しなやかなキャリアの形
kakehashi
PRO
1
180
螺旋型キャリアの生存戦略 / kinoko-conf2026
rakus_dev
1
590
SteampipeとExcel Power QueryでAWS構成定義書の作成を自動化する
jhashimoto
0
170
AI駆動開発を通して感じた、 AI時代のデザイナーの役割変化
whisaiyo
4
2.4k
脱SaaS!FDEを支えるプロビジョニングと分離設計
knih
0
250
事業会社における 機械学習・推薦システム技術の活用事例と必要な能力 / ml-recsys-in-layerx-wantedly-2026
yuya4
0
110
Featured
See All Featured
Site-Speed That Sticks
csswizardry
13
1.2k
How to Think Like a Performance Engineer
csswizardry
28
2.7k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
250
How STYLIGHT went responsive
nonsquared
100
6.2k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Designing Experiences People Love
moore
143
24k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.1k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
ラッコキーワード サービス紹介資料
rakko
1
3.7M
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.4k
Transcript
AIのためのテスト戦略 〜TDDが難しいフロントエンド開発でのアプローチ〜 2025/10/04 横山 隼 ScrumMatsuri 2025
自己紹介 • ディップ株式会社 • 2022年新卒入社 • フロントエンドエンジニア 横山 隼
みなさん、AIコーディングはされていますか?🤔
されていますよね😌
最近は、AIコーディングが当たり前になってきました
開発スピードは爆発的に速くなりました 🚀
とはいえ、まだまだ指示したことと違うことするときがある🤔
関係ないところまで修正に手を出して、
関係ないところまで修正に手を出して、 エラーが出て、
関係ないところまで修正に手を出して、 エラーが出て、 違う治し方して、
関係ないところまで修正に手を出して、 エラーが出て、 違う治し方して、 そうじゃないってなることがある
今回は、AIに開発を任せて、 開発スピードを落とさずにガードレールとなるような
フロントエンドテストの取り組み 5つ紹介します
抽象的な大きな取り組みから、 具体的なテクニック的な話まで含まれます
チーム状況 🧰 技術スタック TypeScript, React Router v7 🧠 AIコーディング JiraやFigmaをMCP経由で
Claude Code に取り込み、実装させる チーム人数 エンジニア3人 少人数ながら AIを活用してスピードと品質の両面を追う
FEがBEと通信する層を厚くテストする
FEがBEと通信する層を厚くテストする • ビジネス上の重要なロジックが集中しやすい層なので 厚くテストする • テスタブルにするために なるべく純粋なTypeScript関数になるようにする
私のチームではReact Router の Loader/Action関数をBFF層として データ取得、整形、送信、バリデーションなどをしている テストケース抜粋 • 名前・メール・電話番号を正しく入力すると、入力内容が返されること • 応募確認画面で閲覧中に求人が締切になったら、応募エラーになること
• 応募ボタン連打しても、二重送信されないこと Loader/Actionをカバレッジ 100%になるように書いている
StorybookのcomposeStoriesで 共通コンポーネントをテストする
「フロントエンドのテストを書いていこう!」とすると よくあることとして...🤔
it("'Hello World' のテキストが表示されること ", () => { render(<Greeting text={"Hello World"}
/>); expect(screen.getByText("Hello World")).toBeInTheDocument(); }); export function Greeting({ text }: GreetingProps) { return <p>{text}</p>; } Propsで渡されたテキストを表示するコンポーネントに対して、 テキストが表示されること ➡ 効果の低いテストを過剰に書いてしまう
一方で🤔
➡ ユーザー操作を含むテストは再現するのが難しく、コストが高い // テスト上でスクロール操作ができないので、スクロール量を上書きする const setScrollY = (y: number) =>
{ Object.defineProperty(window, "scrollY", { configurable: true, value: y, }); window.dispatchEvent(new Event("scroll")); }; it("スクロール量が閾値を超えたらナビゲーションバーが表示される", () => { render(<Navbar />); expect(screen.queryByTestId("navbar")).toBeNull(); setScrollY(120); expect(screen.getByTestId("navbar")).toBeInTheDocument(); });
すべてのコンポーネントに対して、 テストしようとすると過剰になりがち でも、効果が高いインタラクティブな挙動を テストするのはコストが高い
だからこそ、アプリ全体で繰り返し使われる 共通コンポーネントに絞ってテストする
だからこそ、アプリ全体で繰り返し使われる 共通コンポーネントに絞ってテストする ➡ StorybookのcomposeStoriesでテストする
📚 composeStories・・・ Storybookのストーリーをテスト環境で利用できる仕組み const meta: Meta<typeof Button> = { title:
"Components/Button", component: Button, args: { label: "Click Me" }, }; export default meta; type Story = StoryObj<typeof Button>; export const Primary: Story = { args: { disabled: false }, }; export const Disabled: Story = { args: { disabled: true, label: "Disabled" }, }; it("Primary: ~~~~", async () => { render(<Primary onClick={onClick} />); // 略 expect(onClick).toHaveBeenCalledTimes(1); }); it("Disabled: ~~~~", async () => { render(<Disabled onClick={onClick} />); // 略 expect(onClick).not.toHaveBeenCalled(); }); Storybook テスト
📚 composeStories・・・ Storybookのストーリーをテスト環境で利用できる仕組み const meta: Meta<typeof Button> = { title:
"Components/Button", component: Button, args: { label: "Click Me" }, }; export default meta; type Story = StoryObj<typeof Button>; export const Primary: Story = { args: { disabled: false }, }; export const Disabled: Story = { args: { disabled: true, label: "Disabled" }, }; it("Primary: ~~~~", async () => { render(<Primary onClick={onClick} />); // 略 expect(onClick).toHaveBeenCalledTimes(1); }); it("Disabled: ~~~~", async () => { render(<Disabled onClick={onClick} />); // 略 expect(onClick).not.toHaveBeenCalled(); }); Storybook テスト
composeStoriesを使うことで... • ストーリーの更新することでテストも同時に更新され、 ストーリーとテストに乖離が起きない • ストーリーごとに「本番と近い環境」で UI を再現できる
composeStoriesを使うことで... • ストーリーの更新することでテストも同時に更新され、 ストーリーとテストに乖離が起きない • ストーリーごとに「本番と近い環境」で UI を再現できる ➡ 共通コンポーネントに絞ってテストする
AAAパターン
Arrange(準備), Act(実行), Assert(検証)の 3つセクションに明示的に分けた構成でテストを書く it('2つの正の数を正しく足し算できること', () => { // Arrange
(準備): const num1 = 5; const num2 = 3; const expectedSum = 8; // Act (実行): const actualSum = add(num1, num2); // Assert (検証): expect(actualSum).toBe(expectedSum); });
AIコーディングするにあたって、細かなルールで書き方を制限して、 表現の自由度を狭めてあげる
テストケース名は ユーザー/ビジネス視点で記述する
it('応募ボタンを押すと確認画面に進むこと ', () => { ... }); ✅ Good ❌
Bad it('onSubmit が navigate('/confirm') を呼ぶこと', () => { ... }); ユーザーの行動と成果が主語になるように書く
ユーザー体験にどうつながるのか🤔を見極めやすくなる ビジネス的な効果の薄いテストを疑うトリガーになる
テストファイルはコロケーションする
テストファイルは__tests__/とかtests/ に置くのではなく テスト対象のコードの同じディレクトリ配下に置く route/ └── top/ ├── route.tsx └── top.test.tsx
⬅ util/ └── date/ ├── date.test └── date.test.tsx ⬅ tests/ ├── route/ │ ├── top.test.tsx │ └── job-detail.test.tsx └── test/ ├── top.test.tsx └── job-detail.test.tsx ✅ Good ❌ Bad
テストをアプリケーションコードとコロケーションすることで、 • 「隣のテストも直す」意識が働き、 テストのメンテが置き去りになりにくい • 関連ファイルが近接していると、AIが文脈を取り込みやすい 人もAIもテストを見失わないようにするために テストはコロケーションする
さいごに
さいごに • FEがBEを通信する層を厚くテストする • UIは共通コンポーネントに絞ってテストする • 人もAIも迷わないように、書き方・名前・配置を工夫する AIコーディングで開発スピードを上げつつ、テストで品質を支える