90 lines
3.5 KiB
Markdown
90 lines
3.5 KiB
Markdown
# テストポリシー
|
||
|
||
全ての振る舞いの変更には対応するテストが必要であり、全てのバグ修正にはリグレッションテストが必要。
|
||
|
||
## 原則
|
||
|
||
| 原則 | 基準 |
|
||
|------|------|
|
||
| Given-When-Then | テストは3段階で構造化する |
|
||
| 1テスト1概念 | 複数の関心事を1テストに混ぜない |
|
||
| 振る舞いを検証 | 実装の詳細ではなく振る舞いをテストする |
|
||
| 独立性 | 他のテストや実行順序に依存しない |
|
||
| 再現性 | 時間やランダム性に依存せず、毎回同じ結果 |
|
||
|
||
## カバレッジ基準
|
||
|
||
| 対象 | 基準 |
|
||
|------|------|
|
||
| 新しい振る舞い | テスト必須。テストがなければ REJECT |
|
||
| バグ修正 | リグレッションテスト必須。テストがなければ REJECT |
|
||
| 振る舞いの変更 | テストの更新必須。更新がなければ REJECT |
|
||
| エッジケース・境界値 | テスト推奨(Warning) |
|
||
|
||
## テスト優先度
|
||
|
||
| 優先度 | 対象 |
|
||
|--------|------|
|
||
| 高 | ビジネスロジック、状態遷移 |
|
||
| 中 | エッジケース、エラーハンドリング |
|
||
| 低 | 単純なCRUD、UIの見た目 |
|
||
|
||
## テスト構造: Given-When-Then
|
||
|
||
```typescript
|
||
test('ユーザーが存在しない場合、NotFoundエラーを返す', async () => {
|
||
// Given: 存在しないユーザーID
|
||
const nonExistentId = 'non-existent-id'
|
||
|
||
// When: ユーザー取得を試みる
|
||
const result = await getUser(nonExistentId)
|
||
|
||
// Then: NotFoundエラーが返る
|
||
expect(result.error).toBe('NOT_FOUND')
|
||
})
|
||
```
|
||
|
||
## テスト品質
|
||
|
||
| 観点 | 良い | 悪い |
|
||
|------|------|------|
|
||
| 独立性 | 他のテストに依存しない | 実行順序に依存 |
|
||
| 再現性 | 毎回同じ結果 | 時間やランダム性に依存 |
|
||
| 明確性 | 失敗時に原因が分かる | 失敗しても原因不明 |
|
||
| 焦点 | 1テスト1概念 | 複数の関心事が混在 |
|
||
|
||
### 命名
|
||
|
||
テスト名は期待される振る舞いを記述する。`should {期待する振る舞い} when {条件}` パターンを使う。
|
||
|
||
### 構造
|
||
|
||
- Arrange-Act-Assert パターン(Given-When-Then と同義)
|
||
- マジックナンバー・マジックストリングを避ける
|
||
|
||
## テスト戦略
|
||
|
||
- ロジックにはユニットテスト、境界にはインテグレーションテストを優先
|
||
- ユニットテストでカバーできるものにE2Eテストを使いすぎない
|
||
- 新しいロジックにE2Eテストしかない場合、ユニットテストの追加を提案する
|
||
|
||
## テスト環境の分離
|
||
|
||
テストインフラの設定はテストシナリオのパラメータに連動させる。ハードコードされた前提は別シナリオで壊れる。
|
||
|
||
| 原則 | 基準 |
|
||
|------|------|
|
||
| パラメータ連動 | テストの入力パラメータに応じてフィクスチャ・設定を生成する |
|
||
| 暗黙の前提排除 | 特定の環境(ユーザーの個人設定等)に依存しない |
|
||
| 整合性 | テスト設定内の関連する値は互いに矛盾しない |
|
||
| プロセス終了保証 | テストランナーにタイムアウトと強制終了を設定し、プロセスリークを防ぐ |
|
||
|
||
```typescript
|
||
// ❌ ハードコードされた前提 — 別のバックエンドでテストすると不整合になる
|
||
writeConfig({ backend: 'postgres', connectionPool: 10 })
|
||
|
||
// ✅ パラメータに連動
|
||
const backend = process.env.TEST_BACKEND ?? 'postgres'
|
||
writeConfig({ backend, connectionPool: backend === 'sqlite' ? 1 : 10 })
|
||
```
|