2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ユーザー操作をTDDで記述する:UI操作・イベント駆動テストの書き方

Posted at

概要

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設計戦略である。”

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?