概要
TDD(Test-Driven Development)は、ロジックだけでなくUIにも適用できる。
むしろ、ユーザー操作という「最も振る舞いに近い層」にこそ、TDDは真価を発揮する。
本稿では、Vue 3 + Testing Library + Vitest を使って
UIイベント駆動テストをTDDで設計・実装する方法を、段階的に解説する。
1. UIにおけるTDDとは
UIのTDDでは「コンポーネントの内部構造」をテストするのではなく、
ユーザー視点での操作とその結果を仕様として書いていく。
テストの対象は「状態」ではなく「振る舞い」
2. 実装例:ToDo追加フォームのTDD
🔴 Red:まずは失敗する仕様を書く
// AddTodo.spec.ts
import { render, screen } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import AddTodo from './AddTodo.vue'
test('入力後、ボタンをクリックするとToDoが登録される', async () => {
const user = userEvent.setup()
render(AddTodo)
await user.type(screen.getByPlaceholderText('やること'), '牛乳を買う')
await user.click(screen.getByRole('button', { name: '追加' }))
expect(screen.getByText('牛乳を買う')).toBeInTheDocument()
})
3. 🟢 Green:最小構成の実装でテストを通す
<!-- AddTodo.vue -->
<template>
<div>
<input v-model="text" placeholder="やること" />
<button @click="add">追加</button>
<ul>
<li v-for="(todo, i) in todos" :key="i">{{ todo }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
const todos = ref([])
function add() {
if (text.value) {
todos.value.push(text.value)
text.value = ''
}
}
</script>
4. Red-Green-Refactor:UI層でもこの循環は生きる
フェーズ | アクション | 設計上の意義 |
---|---|---|
🔴 Red | 仕様(ユーザー操作)を書く | 要求が明確になる |
🟢 Green | 最小構成で振る舞いを満たす実装を書く | 過剰な機能や構造を避けられる |
🔁 Refactor | DOM構造やメソッドの整理 | 可読性・再利用性が高まる |
5. ユーザー視点のTDD設計指針
✅ テストは「ユーザー操作と言葉」で書く
-
"牛乳を買う"
という入力 -
"追加"
というボタン - 結果として「表示される」ToDo
✅ DOMの詳細に依存しない
-
getByText
,getByPlaceholderText
,getByRole
を活用 -
querySelector
ではなく、ユーザーが見える情報で取得
✅ 内部ロジックの存在を意識しない
- テストは 入力 → 結果 のみを書く
- ローカルステートや関数名に依存しない
設計判断フロー
① どんな操作をするか? → userEventで表現
② 何が画面に表示されるか? → screen.getByTextで表現
③ DOM構造や実装を意識していないか? → NO → ユーザー視点に戻す
④ ボタンが押されたあと、何が見えるか? → YES → 期待結果として明記
よくあるミスと対策
❌ DOM要素のクラス名やIDに依存したテスト
→ ✅ UIは「見える振る舞い」ベースで書く(=ユーザー視点)
❌ 「フォームの値」や「内部のstate」を直接検証
→ ✅ 入力 → 出力の結果でテストすること。中身ではなく結果
❌ プレーンなclick()
やinput.value = ...
で操作する
→ ✅ userEvent
を使って実際のユーザー操作を模倣する
結語
UIにおけるTDDとは、コンポーネントの中身を検査するものではない。
それは**「ユーザーの操作に対して、何が画面に現れるか」を仕様として定義し、実装をそれに従わせるプロセス**である。
- 内部状態ではなく、**ユーザー体験(UX)**をテストに落とし込む
- DOMの構造ではなく、振る舞いと言葉で書く
- UIにもTDDを適用することで、壊れにくく進化しやすい画面設計が可能になる
TDDとは、
“ユーザーの行動をコードとして記述し、インターフェースの期待値を明文化するUI設計戦略である。”