159 lines
5.0 KiB
Markdown
159 lines
5.0 KiB
Markdown
# テスト Fixture 仕様
|
||
|
||
## 概要
|
||
|
||
テスト用 fixture は、実 API のストリーミング応答を JSONL 形式で録画したファイル。
|
||
`MockLlmClient::from_fixture()` でロードし、API キー不要・決定的なテスト実行を実現する。
|
||
|
||
## ファイル形式
|
||
|
||
```
|
||
{メタデータ行: JSON}
|
||
{イベント行: JSON}
|
||
{イベント行: JSON}
|
||
...
|
||
```
|
||
|
||
- **1行目**: メタデータ (`timestamp`, `model`, `description`)
|
||
- **2行目以降**: 録画イベント (`elapsed_ms`, `event_type`, `data`)
|
||
- `data` フィールドに `Event` の JSON 文字列が入る
|
||
|
||
## ファイル配置
|
||
|
||
```
|
||
crates/llm-worker/tests/fixtures/
|
||
anthropic/
|
||
simple_text.jsonl
|
||
tool_call.jsonl
|
||
long_text.jsonl
|
||
openai/
|
||
simple_text.jsonl
|
||
tool_call.jsonl
|
||
long_text.jsonl
|
||
gemini/
|
||
simple_text.jsonl
|
||
tool_call.jsonl
|
||
long_text.jsonl
|
||
ollama/
|
||
simple_text.jsonl
|
||
tool_call.jsonl
|
||
long_text.jsonl
|
||
```
|
||
|
||
## シナリオ定義
|
||
|
||
### simple_text
|
||
|
||
単純なテキスト応答。
|
||
|
||
| 項目 | 値 |
|
||
|---|---|
|
||
| ファイル名 | `simple_text.jsonl` |
|
||
| system prompt | `"You are a helpful assistant. Be very concise."` |
|
||
| user message | `"Say hello in one word."` |
|
||
| max_tokens | 50 |
|
||
| ツール | なし |
|
||
|
||
**期待パターン**:
|
||
- `BlockStart(Text)` が1つ以上
|
||
- `BlockDelta(Text)` が1つ以上
|
||
- `BlockStop(Text)` が1つ以上
|
||
- 応答が短い(1単語程度)
|
||
|
||
**用途**: 基本的なストリーミング動作、Timeline テキスト収集、Worker の単純な run 完了
|
||
|
||
### tool_call
|
||
|
||
ツール呼び出しを含む応答。
|
||
|
||
| 項目 | 値 |
|
||
|---|---|
|
||
| ファイル名 | `tool_call.jsonl` |
|
||
| system prompt | `"You are a helpful assistant. Use tools when appropriate."` |
|
||
| user message | `"What's the weather in Tokyo? Use the get_weather tool."` |
|
||
| max_tokens | 200 |
|
||
| ツール | `get_weather(city: string)` |
|
||
|
||
**期待パターン**:
|
||
- `BlockStart(ToolUse)` を含む
|
||
- ToolUse ブロック内に `tool_call_id`, `name: "get_weather"` がある
|
||
- tool input JSON に `"city"` キーを含む
|
||
|
||
**用途**: ToolCallCollector、Worker のツール実行フロー、Session の ToolResults ログ記録
|
||
|
||
### long_text
|
||
|
||
長文テキスト応答。
|
||
|
||
| 項目 | 値 |
|
||
|---|---|
|
||
| ファイル名 | `long_text.jsonl` |
|
||
| system prompt | `"You are a creative writer."` |
|
||
| user message | `"Write a short story about a robot discovering a garden. It should be at least 300 words."` |
|
||
| max_tokens | 1000 |
|
||
| ツール | なし |
|
||
|
||
**期待パターン**:
|
||
- `BlockDelta(Text)` が複数(ストリーミングチャンク)
|
||
- 最終テキストが 300 語以上
|
||
|
||
**用途**: ストリーミングの分割配信検証、Subscriber のデルタ受信テスト
|
||
|
||
## 共通検証項目
|
||
|
||
全 fixture に対して以下を検証する(`assert_*` ヘルパー関数群):
|
||
|
||
- `assert_events_deserialize` — 全イベントが `Event` にデシリアライズできる
|
||
- `assert_event_sequence` — BlockStart → BlockDelta → BlockStop の基本シーケンス
|
||
- `assert_usage_tokens` — `Usage` イベントが含まれる
|
||
- `assert_timeline_integration` — Timeline に流してテキスト収集できる
|
||
|
||
## 録画手順
|
||
|
||
### 前提
|
||
|
||
- API キーが環境変数に設定されていること
|
||
- `crates/llm-worker` ディレクトリで実行
|
||
|
||
### コマンド
|
||
|
||
```bash
|
||
# 単一シナリオ録画
|
||
ANTHROPIC_API_KEY=... cargo run --example record_test_fixtures -- -s simple_text
|
||
|
||
# 全シナリオ録画
|
||
ANTHROPIC_API_KEY=... cargo run --example record_test_fixtures -- --all
|
||
|
||
# プロバイダー指定
|
||
OPENAI_API_KEY=... cargo run --example record_test_fixtures -- --all -c openai
|
||
GEMINI_API_KEY=... cargo run --example record_test_fixtures -- --all -c gemini
|
||
|
||
# モデル指定
|
||
ANTHROPIC_API_KEY=... cargo run --example record_test_fixtures -- --all -m claude-sonnet-4-20250514
|
||
```
|
||
|
||
### シナリオ定義の場所
|
||
|
||
`crates/llm-worker/examples/record_test_fixtures/scenarios.rs`
|
||
|
||
新しいシナリオを追加する場合はこのファイルに `TestScenario` を追加し、
|
||
`scenarios()` 関数の返り値に含める。
|
||
|
||
## 録画後の確認チェックリスト
|
||
|
||
録画後、テストに組み込む前に以下を手動確認する:
|
||
|
||
- [ ] JSONL の各行が valid JSON か(`jq . < fixture.jsonl` で確認)
|
||
- [ ] 1行目にメタデータ(`timestamp`, `model`, `description`)が入っているか
|
||
- [ ] simple_text: `BlockStart` → `BlockDelta` → `BlockStop` シーケンスがあるか
|
||
- [ ] tool_call: `BlockStart` に `"block_type":"ToolUse"` を含むか
|
||
- [ ] long_text: `BlockDelta` が複数行あるか(ストリーミング分割の確認)
|
||
- [ ] 各 fixture に `Usage` イベントが含まれるか
|
||
- [ ] エラーイベントが混入していないか
|
||
|
||
## 注意事項
|
||
|
||
- fixture は API の応答に依存するため、モデルバージョンアップで再録画が必要になることがある
|
||
- 録画の自動化(CI での定期録画等)は行わない。手動実行 + 目視確認のフロー
|
||
- fixture が存在しない場合、対応するテストは skip される(`if !fixture_path.exists() { return; }` パターン)
|