---
generated_at: 2026-02-04 10:30:00
metrics:
  claims_total: 100
  claims_with_evidence: 97
  claims_without_evidence: 3
confidence_derived: 0.97
---

# 根拠レポート：Component-Stopwatch 単体テストケース一覧

## 本レポートについて

### 目的
本レポートは、生成された設計書・ドキュメントの信頼性を検証し、人間レビュアーが効率的にレビューできるようにすることを目的としています。

### チェック方法
以下の観点でドキュメントの内容（Claim：主張）を検証しています：

1. **根拠の有無確認**：各主張に対して、ソースコード・既存設計書・要件定義書などの根拠（Evidence）が存在するか
2. **根拠との整合性**：主張の内容が根拠と矛盾していないか
3. **網羅性**：参照すべき情報源を適切にカバーしているか

### 信頼度スコアの算出
- **confidence_derived** = 根拠あり件数 / 総主張件数
- 状態「○」：根拠あり、「△」：根拠不足または要確認

### 本レポートの使い方
1. まず「サマリー」で全体の信頼度と優先レビュー項目を確認
2. 「Claims と根拠の対応」で △ の項目を重点的にレビュー
3. 「不足情報」で補完が必要な情報源を確認

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.97**
  - 根拠あり：97 / 100、根拠なし：3
- 優先レビュー（高）
  1. **C-041（getDuration - 実行中period含む計算）**：実行時の時刻に依存するためテスト結果の検証が困難
  2. **C-097（ネストセクション統合確認）**：複合的な操作の統合テストであり、期待結果の具体性が不足
  3. **C-003（memoryの検証）**：memory_get_usage(true)の戻り値はテスト環境に依存

## 2) 参照した情報（Evidence一覧）
> ここに「実在するもの」だけ列挙。抽出フェーズで付けたIDをそのまま出す。

- E-01: `src/Symfony/Component/Stopwatch/StopwatchPeriod.php` - StopwatchPeriodクラス定義（73行）
- E-02: `src/Symfony/Component/Stopwatch/StopwatchEvent.php` - StopwatchEventクラス定義（238行）
- E-03: `src/Symfony/Component/Stopwatch/Section.php` - Sectionクラス定義（155行）
- E-04: `src/Symfony/Component/Stopwatch/Stopwatch.php` - Stopwatchクラス定義（163行）

## 3) Claims と根拠の対応（レビューの主戦場）
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-001 | morePrecision=falseでstart/endがintにキャストされる | E-01 (L32: `$this->start = $morePrecision ? (float) $start : (int) $start`) | ○ |
| C-002 | morePrecision=trueでstart/endがfloatで保持される | E-01 (L32-33) | ○ |
| C-003 | memoryが現在のメモリ使用量で設定される | E-01 (L34: `$this->memory = memory_get_usage(true)`) | △ |
| C-004 | getStartTime()が開始時刻を返却する | E-01 (L40-43) | ○ |
| C-005 | getEndTime()が終了時刻を返却する | E-01 (L48-51) | ○ |
| C-006 | getDuration()がend-startを返却する | E-01 (L56-59: `return $this->end - $this->start`) | ○ |
| C-007 | start=endの場合にDurationが0になる | E-01 (L58: `$this->end - $this->start`) | ○ |
| C-008 | morePrecision=trueでfloat精度の計算 | E-01 (L32-33, L58) | ○ |
| C-009 | getMemory()がint型でメモリを返却する | E-01 (L64-67) | ○ |
| C-010 | __toString()がフォーマットされた文字列を返却する | E-01 (L69-72) | ○ |
| C-011 | start=0, end=0でDurationが0 | E-01 (L58) | ○ |
| C-012 | originがformatTimeで丸められる | E-02 (L48: `$this->origin = $this->formatTime($origin)`, L222-224: `return round($time, 1)`) | ○ |
| C-013 | categoryがnullの場合にdefaultが設定される | E-02 (L49: `$this->category = \is_string($category) ? $category : 'default'`) | ○ |
| C-014 | categoryが指定された場合にその値が設定される | E-02 (L49) | ○ |
| C-015 | nameがnullの場合にdefaultが設定される | E-02 (L50: `$this->name = $name ?? 'default'`) | ○ |
| C-016 | nameが指定された場合にその値が設定される | E-02 (L50) | ○ |
| C-017 | getCategory()がカテゴリを返却する | E-02 (L56-59) | ○ |
| C-018 | getOrigin()がoriginを返却する | E-02 (L64-67) | ○ |
| C-019 | start()でイベントが開始状態になる | E-02 (L74-79: `$this->started[] = $this->getNow()`) | ○ |
| C-020 | start()がstaticを返却する | E-02 (L74: `public function start(): static`) | ○ |
| C-021 | stop()でperiodが追加される | E-02 (L88-97: `$this->periods[] = new StopwatchPeriod(...)`) | ○ |
| C-022 | stop()がstaticを返却する | E-02 (L88: `public function stop(): static`) | ○ |
| C-023 | startせずにstopするとLogicException | E-02 (L90-92: `throw new \LogicException('stop() called but start() has not been called before.')`) | ○ |
| C-024 | start前はisStarted()がfalse | E-02 (L102-105: `return (bool) $this->started`, `$this->started = []`初期値) | ○ |
| C-025 | start後はisStarted()がtrue | E-02 (L76, L104) | ○ |
| C-026 | start/stop後はisStarted()がfalse | E-02 (L93: `array_pop($this->started)`, L104) | ○ |
| C-027 | lap()でperiodが停止し新しいperiodが開始される | E-02 (L112-115: `return $this->stop()->start()`) | ○ |
| C-028 | 複数回lapで対応する数のperiodsが生成される | E-02 (L112-115) | ○ |
| C-029 | ensureStopped()で全periodが停止される | E-02 (L120-125: `while (\count($this->started)) { $this->stop(); }`) | ○ |
| C-030 | 開始中のperiodがない場合にensureStopped()で何も起こらない | E-02 (L122: whileループの条件で0件なら何もしない) | ○ |
| C-031 | getPeriods()が全periodを配列で返却する | E-02 (L132-135) | ○ |
| C-032 | period未生成時にgetPeriods()が空配列を返却する | E-02 (L24: `private array $periods = []`, L134) | ○ |
| C-033 | getLastPeriod()が最後のperiodを返却する | E-02 (L140-147) | ○ |
| C-034 | period未生成時にgetLastPeriod()がnullを返却する | E-02 (L142-144: `if ([] === $this->periods) { return null; }`) | ○ |
| C-035 | getStartTime()が最初のperiodの開始時刻を返却する | E-02 (L152-156: `return $this->periods[0]->getStartTime()`) | ○ |
| C-036 | periodなしでstart中はstarted[0]を返却する | E-02 (L158-160: `if ($this->started) { return $this->started[0]; }`) | ○ |
| C-037 | periodもstartedもない場合にgetStartTime()が0を返却する | E-02 (L162: `return 0`) | ○ |
| C-038 | getEndTime()が最後のperiodの終了時刻を返却する | E-02 (L168-173) | ○ |
| C-039 | periodがない場合にgetEndTime()が0を返却する | E-02 (L172: `return $count ? ... : 0`) | ○ |
| C-040 | getDuration()が全periodの合計durationを返却する | E-02 (L178-193) | ○ |
| C-041 | 実行中のperiodも含めてDurationが合計される | E-02 (L183-185: 実行中startedからStopwatchPeriodを生成) | △ |
| C-042 | periodが0件の場合にgetDuration()が0を返却する | E-02 (L187: `$total = 0`, L192) | ○ |
| C-043 | getMemory()が全periodの最大メモリを返却する | E-02 (L198-208) | ○ |
| C-044 | periodが0件の場合にgetMemory()が0を返却する | E-02 (L200: `$memory = 0`, L207) | ○ |
| C-045 | getName()がイベント名を返却する | E-02 (L229-232) | ○ |
| C-046 | __toString()がフォーマット文字列を返却する | E-02 (L234-237) | ○ |
| C-047 | 複数回start()が呼べる（ネスト計測） | E-02 (L76: `$this->started[]` 配列にpush) | ○ |
| C-048 | Sectionのorigin/morePrecisionが設定される | E-03 (L37-41) | ○ |
| C-049 | originがnullでもSectionが生成される | E-03 (L38: `private ?float $origin = null`) | ○ |
| C-050 | get()で子セクションがIDで取得できる | E-03 (L46-55) | ○ |
| C-051 | 存在しないIDでget()がnullを返却する | E-03 (L54: `return null`) | ○ |
| C-052 | 子セクション0件でget()がnullを返却する | E-03 (L48-54: foreachが実行されずnull返却) | ○ |
| C-053 | open(null)で新しい子セクションが作成される | E-03 (L62-68: `if (null === $id ...`) | ○ |
| C-054 | 存在するidでopen()が既存セクションを返却する | E-03 (L64-65) | ○ |
| C-055 | 存在しないidでopen()が新規セクションを作成する | E-03 (L64: `null === $session = $this->get($id)` の場合新規作成) | ○ |
| C-056 | getId()初期値がnull | E-03 (L26: `private ?string $id = null`) | ○ |
| C-057 | setId()でIDが設定される | E-03 (L81-86) | ○ |
| C-058 | setId()がstaticを返却する | E-03 (L80: `public function setId(string $id): static`) | ○ |
| C-059 | startEvent()で新イベントが開始される | E-03 (L91-98) | ○ |
| C-060 | 既存イベント名で同じイベントが再開される | E-03 (L93-95: `if (!isset($this->events[$name]))` で既存はスキップ) | ○ |
| C-061 | category=nullでdefaultカテゴリが設定される | E-03 (L94) → E-02 (L49) | ○ |
| C-062 | isEventStarted()が開始済みイベントにtrue | E-03 (L103-106) | ○ |
| C-063 | isEventStarted()が存在しないイベントにfalse | E-03 (L105: `isset($this->events[$name])` がfalse) | ○ |
| C-064 | isEventStarted()が停止済みイベントにfalse | E-03 (L105) → E-02 (L104) | ○ |
| C-065 | stopEvent()で開始済みイベントが停止される | E-03 (L113-120) | ○ |
| C-066 | stopEvent()で存在しないイベントにLogicException | E-03 (L115-117: `throw new \LogicException(...)`) | ○ |
| C-067 | lap()でイベントのラップが動作する | E-03 (L127-130: `return $this->stopEvent($name)->start()`) | ○ |
| C-068 | lap()で存在しないイベントにLogicException | E-03 (L129: `$this->stopEvent($name)` → L115-117) | ○ |
| C-069 | getEvent()で存在するイベントが返却される | E-03 (L137-144) | ○ |
| C-070 | getEvent()で存在しないイベントにLogicException | E-03 (L139-141: `throw new \LogicException(...)`) | ○ |
| C-071 | getEvents()が全イベントを配列で返却する | E-03 (L151-154) | ○ |
| C-072 | イベント0件でgetEvents()が空配列を返却する | E-03 (L24: `private array $events = []`, L153) | ○ |
| C-073 | Stopwatch(false)でインスタンスが生成される | E-04 (L41-45) | ○ |
| C-074 | Stopwatch(true)でインスタンスが生成される | E-04 (L41-45) | ○ |
| C-075 | コンストラクタでreset()が呼ばれ初期状態になる | E-04 (L44: `$this->reset()`, L159-162) | ○ |
| C-076 | getSections()がセクション一覧を返却する | E-04 (L50-53) | ○ |
| C-077 | openSection(null)で新セクションが開かれる | E-04 (L62-73) | ○ |
| C-078 | 存在しないidでopenSection()にLogicException | E-04 (L66-68: `throw new \LogicException(...)`) | ○ |
| C-079 | stopSection()でセクションが閉じられる | E-04 (L84-94) | ○ |
| C-080 | セクション未開始時にstopSection()にLogicException | E-04 (L88-90: `throw new \LogicException(...)`) | ○ |
| C-081 | start()でイベントが開始される | E-04 (L99-102) → E-03 (L91-98) | ○ |
| C-082 | カテゴリ指定でstart()が動作する | E-04 (L99: `?string $category = null`) → E-03 (L91) | ○ |
| C-083 | isStarted()が開始済みイベントにtrue | E-04 (L107-110) → E-03 (L103-106) | ○ |
| C-084 | isStarted()が未開始イベントにfalse | E-04 (L107-110) → E-03 (L103-106) | ○ |
| C-085 | stop()でイベントが停止される | E-04 (L115-118) → E-03 (L113-120) | ○ |
| C-086 | 未開始イベントのstop()にLogicException | E-04 (L115-118) → E-03 (L115-117) | ○ |
| C-087 | lap()でイベントのラップが動作する | E-04 (L123-126) → E-03 (L127-130) | ○ |
| C-088 | getEvent()で存在するイベントが返却される | E-04 (L131-134) → E-03 (L137-144) | ○ |
| C-089 | getEvent()で存在しないイベントにLogicException | E-04 (L131-134) → E-03 (L139-141) | ○ |
| C-090 | getSectionEvents()でセクションイベントが取得できる | E-04 (L141-144) | ○ |
| C-091 | 存在しないセクションIDでgetSectionEvents()が空配列を返却する | E-04 (L143: `isset($this->sections[$id]) ? ... : []`) | ○ |
| C-092 | getRootSectionEvents()でルートイベントが取得できる | E-04 (L151-154) | ○ |
| C-093 | ルートセクションにイベントがない場合に空配列が返却される | E-04 (L153) → E-03 (L151-154: 空のeventsが返却) | ○ |
| C-094 | reset()で初期状態に戻る | E-04 (L159-162) | ○ |
| C-095 | reset後に新たにイベントを開始できる | E-04 (L159-162, L99-102) | ○ |
| C-096 | セクション内でイベントを開始・停止できる | E-04 (L62-73, L99-102, L115-118) | ○ |
| C-097 | ネストされたセクションが正しく動作する | E-04 (L62-73, L84-94) | △ |
| C-098 | 複数回のstart/stopで複数periodが記録される | E-02 (L76, L94) | ○ |
| C-099 | morePrecision=trueでfloat精度のdurationが返却される | E-02 (L45, L94) → E-01 (L32-33) | ○ |
| C-100 | originがnullの場合にイベント開始時の現在時刻がoriginとなる | E-03 (L94: `$this->origin ?: microtime(true) * 1000`) | ○ |

## 4) 不足情報（Unknown / Missing）
- **C-003（memory検証）**: `memory_get_usage(true)`の戻り値はテスト実行環境のメモリ割り当て状態に依存するため、具体的な期待値を事前に決定できない。テストでは「0より大きい整数値」という形で検証する必要がある。
  - 候補：テスト環境でのメモリ状態をモック化 / 範囲での検証 / memory_get_usage(true)の最小保証値の調査
- **C-041（実行中period含むDuration計算）**: getNow()が`microtime(true) * 1000 - origin`を使用するため、テスト実行のタイミングに結果が依存する。厳密な値の検証が困難。
  - 候補：StopwatchEventを継承しgetNow()をオーバーライドしたテスト用サブクラス / sleep()を使った近似値検証 / 保護メソッドのモック化
- **C-097（ネストセクション）**: 複数のopenSection/stopSectionの組み合わせによる統合的な動作であり、内部のactiveSections配列の状態遷移の完全な検証が外部APIからは困難。
  - 候補：セクションの戻り値検証 / getSections()での存在確認 / getSectionEvents()での各セクション別イベント確認

## 5) リスクフラグ（レビュー観点）
- **0（低リスク）**: StopwatchPeriodのgetter系テスト（C-004〜C-011） - 単純な値の取得であり、ロジック誤りの可能性が低い
- **0（低リスク）**: StopwatchEventのcategory/name/originの初期値テスト（C-012〜C-018） - コンストラクタの引数処理が明確
- **1（中リスク）**: StopwatchEventのstart/stop/lap/ensureStopped（C-019〜C-030） - 状態管理が含まれ、ネストされたstart呼び出しの挙動に注意が必要
- **1（中リスク）**: StopwatchEventのgetDuration()（C-040〜C-042） - 実行中periodを含む計算ロジックが時刻に依存
- **1（中リスク）**: SectionのstartEvent/stopEvent/lap（C-059〜C-068） - 内部でStopwatchEventへの委譲が行われ、エラーパスの検証が重要
- **1（中リスク）**: StopwatchのopenSection/stopSection（C-077〜C-080） - セクションのネスト管理が複雑で、activeSectionsの操作に注意が必要
- **2（高リスク）**: ネストセクションの統合動作（C-097） - 複数のセクション操作の組み合わせにより、予期しない状態遷移が発生する可能性

## 6) レビュアーチェックリスト（最小）
- [ ] StopwatchPeriodのmorePrecisionフラグによるint/float型キャストが正しくテストされているか（C-001, C-002）
- [ ] StopwatchEventのstart/stop/lap/ensureStoppedの状態遷移テストが網羅的か（C-019〜C-030）
- [ ] StopwatchEventのgetDuration()テストで実行中periodの計算が含まれているか（C-041）
- [ ] LogicExceptionがスローされるべき全ケースがテストされているか（C-023, C-066, C-068, C-070, C-078, C-080, C-086, C-089）
- [ ] Sectionの子セクション検索（get/open）のエッジケースが網羅されているか（C-050〜C-055）
- [ ] Stopwatchのreset()後に正常に再利用できることが検証されているか（C-094, C-095）
- [ ] ネストされたセクションの開始・停止順序に関する統合テストの具体性は十分か（C-097）
- [ ] memory_get_usage(true)に依存するテストの検証方法が適切か（C-003, C-009, C-043）
