Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
AIのためのテスト戦略 〜TDDが難しいフロントエンド開発でのアプローチ〜
Search
Hayato Yokoyama
October 04, 2025
Technology
280
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
150
「バイトル」のTypeScriptリニューアル — 積み上がったレガシーとパフォーマンスに挑む現在地
hayato_yokoyama
0
110
AIが特別じゃなくなった時代に、作ることを楽しもう
hayato_yokoyama
0
38
実はすごいスピードで進化しているCSS
hayato_yokoyama
0
260
Next.js AppRouter × GraphQL 〜 夢見た理想と現実の課題 〜
hayato_yokoyama
0
180
フロントエンドテストを書きやすくするために工夫したこと
hayato_yokoyama
1
95
Other Decks in Technology
See All in Technology
顧客の成果創出とプロダクトの成長を 両立するためのFDE
sansantech
PRO
0
650
AIに攻撃される前に、AIに攻撃させる
tsuchikazu
0
130
大阪オフィスに Unitree Go2 がやってきたので Physical AI やってみた
dafujii
0
260
カンファレンスに参加した後の浮遊感とセルフケア
pauli
0
310
[2026 Oracle Technical Deep Dive] オンプレミスDBのCloud移行アプローチ:移行計画に基づくメソッドとツールの選択 (2026年9月17日開催)
oracle4engineer
PRO
0
120
組み立てて楽しむ AWS Blocks 入門
kmiya84377
0
190
自律型 AI をセキュアに実装!Gemini と MIG で作る動的コード実行環境
recruitengineers
PRO
1
180
LLM機能を自作して分かるSnowflake Cortex AIの強み
nayuts
0
240
The kernel report
ennael
PRO
1
230
20260929_AmazonGuardDutyの検出通知メールにAWS DevOpsAgentの調査結果を追加する
yhana
1
430
1人アドミンな私はAWSアカウント申請をSlackで完結したい!
ysuzuki
0
110
Incremental HTTP
kazuho
5
2k
Featured
See All Featured
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
ラッコキーワード サービス紹介資料
rakko
1
5.1M
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
910
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
480
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
How to build a perfect <img>
jonoalderson
1
6.1k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
The Curse of the Amulet
leimatthew05
3
15k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
1
550
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コーディングで開発スピードを上げつつ、テストで品質を支える