Skip to content
222 changes: 222 additions & 0 deletions dev-reports/design/issue-80-design-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# 設計方針書: Issue #80 Phase 6 E2E統合テスト

## 1. 概要

Phase 6のチーム向け機能(共有設定、インデックス共有、status拡張)を通したE2E統合テストを作成する。

| 項目 | 内容 |
|------|------|
| Issue | #80 |
| タイプ | テスト追加(プロダクションコード変更なし) |
| スコープ | 7つのE2Eテストシナリオ |
| テストファイル | `tests/e2e_team_workflow.rs` |

## 2. テスト設計方針

### 2.1 既存テストとの差別化

| テストファイル | 役割 | テスト粒度 |
|--------------|------|-----------|
| `tests/cli_status.rs` | status機能の単体・結合テスト | 関数レベル + CLI引数 |
| `tests/cli_export.rs` | export機能の単体テスト | 関数レベル |
| `tests/cli_import.rs` | import機能の単体テスト | 関数レベル |
| `tests/e2e_export_import.rs` | export→import基本フロー | 2機能連携 |
| `tests/e2e_verify.rs` | verify機能のE2E | 単機能CLI |
| **`tests/e2e_team_workflow.rs`** | **チーム運用シナリオの統合フロー** | **複数機能の連携** |

### 2.2 テストパターン

各テストは以下のパターンに従う:

```rust
#[test]
fn scenario_name() {
// 1. Setup: tempdir + テストデータ配置 + 設定ファイル作成
let dir = tempfile::tempdir().expect("create temp dir");

// 2. Act: CLIコマンド実行(assert_cmd経由)
common::cmd()
.args(["subcommand", "--path", dir.path().to_str().unwrap()])
.assert()
.success();

// 3. Assert: 出力/状態の検証
}
```

### 2.3 CLI経由テスト vs API直接テスト

- **CLI経由テスト(assert_cmd)**: 全シナリオで採用。実際のユーザー操作を再現。
- **API直接テスト**: export/importのみ `current_dir` 制約回避のため併用可能。

### 2.4 current_dir依存コマンドの制約

以下のコマンドは `--path` オプションを持たず、カレントディレクトリ(`Path::new(".")`)基準で動作する。テストでは `.current_dir(tmp_dir)` の設定が必須。

| コマンド | current_dir依存 | --pathオプション |
|---------|----------------|-----------------|
| `config show` | あり | なし |
| `config path` | あり | なし |
| `export` | あり | なし |
| `import` | あり | なし |
| `search` | あり(config読込) | なし(--path=prefix filter) |
| `index` | なし | あり |
| `status` | なし | あり |
| `clean` | なし | あり |

## 3. テストシナリオ詳細設計

### シナリオ1: 共有設定フルフロー

```
Setup: commandindex.toml に search.default_limit = 5 を書き込み
テスト用Markdownファイルを配置
Act: index → config show
Assert: config show出力に default_limit = 5 が含まれる
```

### シナリオ2: 設定優先順位

```
Setup: commandindex.toml に search.default_limit = 5
.commandindex/config.local.toml に search.default_limit = 3
Act: config show
Assert: default_limit = 3(local が team を上書き)
```

### シナリオ3: config show(APIキーマスク)

```
Setup: .commandindex/config.local.toml に embedding.api_key = "sk-test123"
Act: config show
Assert: 出力に "***" が含まれ "sk-test123" が含まれない
```

### シナリオ4: エクスポート/インポートフロー

```
Setup: テスト用Markdownファイル配置 → index → search確認
Act: export → clean → import
Assert: import後のsearch結果が元と一致
```

既存 `e2e_export_import.rs` との差別化: search結果の詳細比較(ファイル名・セクション数)

### シナリオ5: status --verify

```
Setup: index で正常なインデックス作成
Act: status --verify
Assert: "Verify: OK" が出力される
```

既存 `e2e_verify.rs` との差別化: チーム設定と組み合わせた検証(commandindex.tomlあり環境)

### シナリオ6: status --detail

```
Setup: テスト用ファイル配置 → index
Act: status --detail
Assert: Coverage/Storage セクションが出力される
```

### シナリオ7: status --format json

```
Setup: テスト用ファイル配置 → index
Act: status --format json --detail
Assert: JSONパース成功、coverage/storage フィールド存在
```

## 4. テストヘルパー設計

### 4.1 既存ヘルパー(tests/common/mod.rs)

| 関数 | 用途 |
|------|------|
| `cmd()` | CLIバイナリのCommand生成 |
| `run_index(path)` | インデックス作成 |
| `run_search_jsonl(path, query)` | 検索+JSONL解析 |
| `run_status_json(path)` | status JSON取得 |
| `run_clean(path)` | インデックス削除 |

### 4.2 新規ヘルパー

```rust
/// commandindex.toml をリポジトリルートに作成
fn write_commandindex_toml(base_path: &Path, content: &str) {
std::fs::write(base_path.join("commandindex.toml"), content)
.expect("write commandindex.toml");
}

/// .commandindex/config.local.toml を作成
fn write_config_local_toml(base_path: &Path, content: &str) {
let dir = base_path.join(".commandindex");
std::fs::create_dir_all(&dir).expect("create .commandindex");
std::fs::write(dir.join("config.local.toml"), content)
.expect("write config.local.toml");
}

/// Git リポジトリを初期化(staleness テスト用)
fn init_git_repo(path: &Path) {
std::process::Command::new("git")
.args(["init"])
.current_dir(path)
.output()
.expect("git init");
std::process::Command::new("git")
.args(["add", "."])
.current_dir(path)
.output()
.expect("git add");
std::process::Command::new("git")
.args(["commit", "-m", "initial"])
.current_dir(path)
.output()
.expect("git commit");
}
```

### 4.3 ヘルパー配置方針

新規ヘルパーは `tests/e2e_team_workflow.rs` 内にローカル関数として定義する。
`tests/common/mod.rs` への追加は最小限にし、既存テストへの影響を避ける。

## 5. 影響範囲

### 変更対象

| ファイル | 変更内容 |
|---------|---------|
| `tests/e2e_team_workflow.rs` | **新規作成**: 7テストシナリオ |

### 影響なし

- プロダクションコード(src/配下): 変更なし
- 既存テストファイル: 変更なし
- Cargo.toml: dev-dependencies追加なし

## 6. 品質基準

| チェック項目 | コマンド | 基準 |
|-------------|----------|------|
| ビルド | `cargo build` | エラー0件 |
| Clippy | `cargo clippy --all-targets -- -D warnings` | 警告0件 |
| テスト | `cargo test --all` | 全テストパス |
| フォーマット | `cargo fmt --all -- --check` | 差分なし |

## 7. 設計判断とトレードオフ

| 判断 | 選択 | 理由 |
|------|------|------|
| テストファイル数 | 1ファイルにまとめる | テストバイナリ数増加を抑制、CI時間最適化 |
| ヘルパー配置 | テストファイル内ローカル | common/mod.rs への影響を回避 |
| テスト粒度 | CLI経由のE2E | ユーザー操作を忠実に再現 |
| マルチリポジトリ | スコープ外 | Issue #78未実装 |
| 環境変数テスト | スコープ外 | load_configに環境変数オーバーライド未実装 |

## 8. セキュリティ考慮

- テスト内でAPIキーのダミー値を使用する場合、マスク処理の動作確認に限定
- テストファイルに実際の秘密情報を含めない
- tempfile::tempdir()によるテスト分離で他テストへの干渉を防止
34 changes: 34 additions & 0 deletions dev-reports/issue/80/issue-review/hypothesis-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 仮説検証レポート: Issue #80

## 検証日: 2026-03-22

## 検証対象

Issue #80のE2E統合テストシナリオの前提条件(依存機能の実装状態)

## 検証結果サマリー

| # | テストシナリオ | 前提機能 | 実装状態 | 判定 |
|---|--------------|---------|---------|------|
| 1 | 共有設定フルフロー | config module (commandindex.toml) | 実装済み | Confirmed |
| 2 | 設定優先順位 | config merge logic | 実装済み | Confirmed |
| 3 | config show | cli/config.rs | 実装済み | Confirmed |
| 4 | エクスポート/インポート | cli/export.rs, cli/import_index.rs | 実装済み | Confirmed |
| 5 | status --verify | cli/status/mod.rs (VerifyResult) | 実装済み | Confirmed |
| 6 | マルチリポジトリ検索 | ワークスペース横断検索 | **未実装** | **Rejected** |
| 7 | status --detail | cli/status/mod.rs (detail flag) | 実装済み | Confirmed |
| 8 | status --format json | cli/status/mod.rs (StatusFormat) | 実装済み | Confirmed |

## 重要な発見

### マルチリポジトリ検索(シナリオ6)が未実装

- コードベースにワークスペース/マルチリポジトリ関連の実装が存在しない
- Issue #78(マルチリポジトリ横断検索)の依存が未解決
- searchコマンドに `--path` フラグ(リポジトリ指定)が存在しない

### 推奨アクション

- シナリオ6(マルチリポジトリ検索)はE2Eテスト対象から除外する
- 実装済みの7シナリオに集中してE2Eテストを作成する
- マルチリポジトリ検索は Issue #78 の実装完了後に別途テストを追加する
1 change: 1 addition & 0 deletions dev-reports/issue/80/issue-review/original-issue.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"body":"## 概要\n\nPhase 6 のチーム向け機能(共有設定、インデックス共有、マルチリポジトリ、status拡張)を通したE2E統合テストを作成する。\n\n## テストシナリオ\n\n1. **共有設定フルフロー**: `commandindex.toml` 作成 → index → 設定が反映される\n2. **設定優先順位**: 環境変数 > config.local.toml > commandindex.toml > デフォルト\n3. **config show**: 有効設定の表示\n4. **インデックスエクスポート/インポート**: index → export → clean → import → search が動作する\n5. **status --verify**: インデックスの整合性チェック\n6. **マルチリポジトリ検索**: 2つのリポジトリを作成 → ワークスペース設定 → 横断検索\n7. **status --detail**: 詳細統計情報の表示\n8. **status --format json**: JSON出力\n\n## テスト環境の前提\n\n- 一時ディレクトリで複数リポジトリをセットアップ\n- Git初期化してテストデータを配置\n- ワークスペース設定ファイルを動的生成\n\n## 受け入れ基準\n\n- [ ] 上記8シナリオのテストが全てPASS\n- [ ] テストは独立して実行可能\n- [ ] cargo test / clippy / fmt 全パス\n\n## 依存 Issue\n\n- #76 チーム共有設定ファイル\n- #77 インデックス共有モード\n- #78 マルチリポジトリ横断検索\n- #79 チーム向けstatusコマンド拡張","title":"[Feature] Phase 6 E2E統合テスト(チーム機能検証)"}
60 changes: 60 additions & 0 deletions dev-reports/issue/80/issue-review/stage1-review-context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"stage": 1,
"type": "normal-review",
"reviewer": "Claude (opus)",
"must_fix": [
{
"id": "M1",
"title": "シナリオ6(マルチリポジトリ検索)は依存Issue #78が未実装で実装不可能",
"description": "ワークスペース・マルチリポジトリ関連のコードが一切存在しないため実装できない。受け入れ基準の「8シナリオ全てPASS」と矛盾。",
"suggestion": "シナリオ6をスコープから除外し、受け入れ基準を7シナリオに修正する。"
},
{
"id": "M2",
"title": "シナリオ2(設定優先順位)の環境変数オーバーライドが未実装",
"description": "load_config()は環境変数から設定値を読み込むロジックを持っていない。COMMANDINDEX_OPENAI_API_KEYはマスク判定にのみ使用。",
"suggestion": "テストシナリオ2の範囲を「config.local.toml > commandindex.toml > デフォルト」の3段階に限定する。"
}
],
"should_fix": [
{
"id": "S1",
"title": "既存テスト数の記載が不正確",
"description": "cli_export.rsは実際6テスト、cli_import.rsは実際9テスト。",
"suggestion": "正確なテスト数に修正する。"
},
{
"id": "S2",
"title": "Export/ImportコマンドにCLI --pathオプションが存在しない",
"description": "常にカレントディレクトリを使用。E2Eテストではcurrent_dir()の切り替えが必要。",
"suggestion": "テストシナリオ4の実装方針にcurrent_dir切り替えの必要性を追記。"
},
{
"id": "S3",
"title": "シナリオ1の検証ポイントが不明確",
"description": "設定反映の検証方法が不明。config showか、検索挙動か。",
"suggestion": "具体的な検証方法を明記する。"
}
],
"nice_to_have": [
{
"id": "N1",
"title": "シナリオ3はE2E統合テストというより単体機能テスト",
"description": "config showは単独で動作。シナリオ1の一部に組み込む方が統合テストらしい。",
"suggestion": "シナリオ1の一部としてconfig show確認を組み込む。"
},
{
"id": "N2",
"title": "テスト独立性の具体的な基準が未定義",
"description": "tempfile::tempdir()での独立性確保を明記すべき。",
"suggestion": "具体的な独立性基準を追記。"
},
{
"id": "N3",
"title": "既存E2Eテストとの重複・統合方針が不明",
"description": "e2e_export_import.rs, e2e_verify.rsとの重複可能性。",
"suggestion": "既存テストとの関係性を明記する。"
}
],
"summary": "Must Fix 2件: シナリオ6は未実装機能への依存、シナリオ2は環境変数オーバーライド未実装。Should Fix 3件: テスト数不正確、--pathオプション制約、検証ポイント不明確。"
}
15 changes: 15 additions & 0 deletions dev-reports/issue/80/issue-review/stage2-apply-result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"stage": 2,
"type": "apply-review",
"applied_fixes": [
"M1: シナリオ6(マルチリポジトリ検索)をスコープから除外。8→7シナリオに変更",
"M2: 設定優先順位を3段階に限定(環境変数オーバーライド未実装を明記)",
"S1: 既存テスト数を正確な値に修正(cli_export: 6, cli_import: 9)",
"S2: export/importのcurrent_dir切替必要性を追記",
"S3: シナリオ1の検証方法を具体化(config showで確認)",
"N2: テスト独立性をtempfile::tempdir()使用と明記",
"N3: 既存テストとの関係セクションを追加"
],
"issue_updated": true,
"url": "https://github.com/Kewton/CommandIndex/issues/80"
}
57 changes: 57 additions & 0 deletions dev-reports/issue/80/issue-review/stage3-review-context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"stage": 3,
"type": "impact-analysis",
"reviewer": "Claude (opus)",
"must_fix": [
{
"id": "MF-1",
"title": "マージコンフリクト残存",
"description": "git statusにコンフリクト残存の可能性",
"note": "Stage 2反映前の状態で検出。実際には会話冒頭で解決済み。対応不要。"
},
{
"id": "MF-2",
"title": "既存テストとの重複・競合",
"description": "シナリオ4-7は既存テストと実質同等のテストが存在する可能性。Issue #80は「チーム機能連携」の観点に限定し差別化する必要がある。",
"suggestion": "既存テストが個別機能テスト、Issue #80がチーム運用シナリオ全体フローという位置づけを明確にする。"
}
],
"should_fix": [
{
"id": "SF-1",
"title": "テスト実行時間の増加",
"description": "7シナリオ追加でCI時間30-50秒増加見込み。テストファイルは1つにまとめてバイナリ数を増やさない。",
"suggestion": "tests/e2e_team_workflow.rs等にまとめる。"
},
{
"id": "SF-2",
"title": "テストヘルパー不足",
"description": "config show、commandindex.toml設定、config.local.toml用のヘルパーが未整備。",
"suggestion": "tests/common/mod.rsにヘルパーを追加する。"
},
{
"id": "SF-3",
"title": "Git初期化ヘルパー未整備",
"description": "staleness情報やgit_commit_hash取得にGitリポジトリが必要。init_git_repoヘルパーが必要。",
"suggestion": "tests/common/mod.rsにinit_git_repo()を追加する。"
}
],
"nice_to_have": [
{
"id": "NH-1",
"title": "依存関係への影響なし",
"description": "新規crate追加不要。"
},
{
"id": "NH-2",
"title": "並列実行安全性",
"description": "環境変数操作を避け、current_dirで分離する。"
},
{
"id": "NH-3",
"title": "テスト命名規則",
"description": "e2e_team_*.rsのような命名推奨。"
}
],
"summary": "主要リスク: (1)既存テストとの重複(差別化必要), (2)テストヘルパー不足(config/git init用), (3)テスト実行時間増加(30-50秒)。依存関係への影響なし。"
}
Loading
Loading