# 機能設計書 26-assert

## 概要

本ドキュメントは、Node.jsのassertモジュールの機能設計について記述する。assertモジュールは、テスト用のアサーション関数を提供し、条件が満たされない場合にAssertionErrorをスローする。単体テストやデバッグ時の値検証に広く使用される。

### 本機能の処理概要

**業務上の目的・背景**：assertモジュールは、プログラムの正しさを検証するためのアサーション機能を提供する。期待値と実際の値の比較、例外発生の検証、正規表現マッチングなど、様々な検証パターンをサポートする。テスト駆動開発（TDD）やデバッグにおいて、コードの振る舞いを確認するために不可欠な機能である。

**機能の利用シーン**：
- 単体テストで期待値と実際の値を比較する際
- オブジェクトの深い比較を行う際
- 関数が例外をスローすることを検証する際
- 関数が例外をスローしないことを検証する際
- Promiseがリジェクトされることを検証する際
- 文字列が正規表現にマッチすることを検証する際

**主要な処理内容**：
1. `assert(value)` / `assert.ok(value)` - 値がtruthyであることを検証
2. `assert.equal(actual, expected)` - 緩い等価性（==）で比較
3. `assert.strictEqual(actual, expected)` - 厳密等価性（===）で比較
4. `assert.deepEqual(actual, expected)` - オブジェクトの深い比較（緩い）
5. `assert.deepStrictEqual(actual, expected)` - オブジェクトの深い比較（厳密）
6. `assert.notEqual()` / `assert.notStrictEqual()` - 不等価の検証
7. `assert.notDeepEqual()` / `assert.notDeepStrictEqual()` - 深い不等価の検証
8. `assert.throws(fn, error)` - 例外発生の検証
9. `assert.doesNotThrow(fn)` - 例外非発生の検証
10. `assert.rejects(promise, error)` - Promiseリジェクトの検証
11. `assert.doesNotReject(promise)` - Promiseリジェクト非発生の検証
12. `assert.match(string, regexp)` - 正規表現マッチの検証
13. `assert.doesNotMatch(string, regexp)` - 正規表現非マッチの検証
14. `assert.fail([message])` - 強制的にAssertionErrorをスロー
15. `assert.ifError(err)` - エラーがnull/undefinedでないことを検証
16. `assert.partialDeepStrictEqual(actual, expected)` - 部分一致の深い比較

**関連システム・外部連携**：
- internal/assert/assertion_error - AssertionErrorクラス
- internal/util/comparisons - 深い比較アルゴリズム

**権限による制御**：特になし。すべての機能は任意のユーザーコードから利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本モジュールはAPI機能であり、関連する画面はありません |

## 機能種別

テスト支援 / アサーション / デバッグ

## 入力仕様

### 入力パラメータ

#### assert / assert.ok

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | any | Yes | 検証する値 | - |
| message | string \| Error | No | 失敗時のメッセージ | - |

#### assert.equal / assert.strictEqual

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| actual | any | Yes | 実際の値 | - |
| expected | any | Yes | 期待値 | - |
| message | string \| Error | No | 失敗時のメッセージ | - |

#### assert.deepEqual / assert.deepStrictEqual

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| actual | any | Yes | 実際の値 | - |
| expected | any | Yes | 期待値 | - |
| message | string \| Error | No | 失敗時のメッセージ | - |

#### assert.throws

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| fn | Function | Yes | 実行する関数 | validateFunction |
| error | Error \| Function \| RegExp \| Object | No | 期待するエラー | - |
| message | string | No | 失敗時のメッセージ | - |

#### assert.match

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| string | string | Yes | 検証する文字列 | - |
| regexp | RegExp | Yes | マッチする正規表現 | isRegExp |
| message | string \| Error | No | 失敗時のメッセージ | - |

#### new Assert(options)

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| options.diff | 'full' \| 'simple' | No | 差分表示モード | validateOneOf |
| options.strict | boolean | No | strictモード（デフォルトtrue） | - |
| options.skipPrototype | boolean | No | プロトタイプ比較をスキップ | - |

### 入力データソース

プログラムコードからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 検証成功時 | void | 何も返さない |
| 検証失敗時 | throw AssertionError | エラーをスロー |

### 出力先

アサーション成功時は何も出力しない。失敗時はAssertionErrorをスローする。

## 処理フロー

### 処理シーケンス

```
1. 引数の検証
   └─ 必要に応じて型チェック
2. 条件の評価
   └─ 比較アルゴリズムの実行
3. 結果の判定
   ├─ 成功: 正常リターン
   └─ 失敗: AssertionErrorをスロー
```

### フローチャート

```mermaid
flowchart TD
    A[アサーション関数呼び出し] --> B{条件評価}
    B -->|成功| C[正常リターン]
    B -->|失敗| D[AssertionError生成]
    D --> E[スタックトレース設定]
    E --> F[エラーをスロー]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | strict版の等価性 | Object.is()を使用した厳密比較 | strictEqual |
| BR-002 | 深い比較 | プロトタイプチェーンを含めたオブジェクト比較 | deepStrictEqual |
| BR-003 | 非strict版の等価性 | ==演算子を使用（NaN==NaNはtrue扱い） | equal |
| BR-004 | エラー曖昧引数 | error引数が文字列の場合はmessageとして扱う | throws/rejects |
| BR-005 | assert.strictモード | equal/deepEqualがstrict版として動作 | assert.strict使用時 |

### 計算ロジック

#### deepStrictEqual比較（internal/util/comparisons）
1. 型の一致確認
2. プリミティブ値の比較（Object.is使用）
3. オブジェクトのプロパティ再帰比較
4. 循環参照の検出と処理

## データベース操作仕様

### 操作別データベース影響一覧

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| AssertionError | Error | アサーション失敗 | 期待値と実際値を確認 |
| ERR_MISSING_ARGS | TypeError | 必須引数がない | actual、expectedを指定 |
| ERR_INVALID_ARG_TYPE | TypeError | 引数の型が不正 | 正しい型の引数を渡す |
| ERR_AMBIGUOUS_ARGUMENT | TypeError | error/messageが曖昧 | 引数を明確に指定 |

### リトライ仕様

リトライ処理は行わない。

## トランザクション仕様

トランザクション処理は行わない。

## パフォーマンス要件

- 深い比較アルゴリズムは遅延ロード（lazyLoadComparison）
- 比較ロジックは最適化されているが、大きなオブジェクトでは時間がかかる可能性

## セキュリティ考慮事項

特になし。テスト・デバッグ用途のため。

## 備考

- assert.strictは厳密比較版のassert
- Assertクラスでインスタンスオプションを設定可能
- AssertionErrorはactual/expected/operatorプロパティを持つ
- options.diff='full'で完全な差分を表示

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | assert.js | `lib/assert.js` | AssertクラスとkOptionsシンボル（69, 105-132行目） |

**読解のコツ**: Assertクラスはnew Assertで生成され、オプション（diff、strict、skipPrototype）を保持する。kOptionsシンボルでオプションにアクセスする。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | assert.js | `lib/assert.js` | module.exports = assert（86行目） |
| 2-2 | assert.js | `lib/assert.js` | assert.strict（894-902行目） |

**主要処理フロー**:
1. **86行目**: assert関数をデフォルトエクスポート
2. **885-892行目**: Assert.prototypeのメソッドをassertにコピー
3. **894-902行目**: assert.strictの設定

#### Step 3: 基本的なアサーション関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | assert.js | `lib/assert.js` | Assert.prototype.ok（196-198行目） |
| 3-2 | assert.js | `lib/assert.js` | Assert.prototype.strictEqual（355-369行目） |
| 3-3 | assert.js | `lib/assert.js` | Assert.prototype.deepStrictEqual（305-320行目） |

**主要処理フロー**:
- **196-198行目**: innerOk関数で値のtruthyチェック
- **355-369行目**: Object.is()で厳密比較、失敗時はinnerFail呼び出し
- **305-320行目**: isDeepStrictEqual()で深い比較、skipPrototypeオプション対応

#### Step 4: 例外検証関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | assert.js | `lib/assert.js` | Assert.prototype.throws（727-729行目） |
| 4-2 | assert.js | `lib/assert.js` | expectsError関数（622-673行目） |
| 4-3 | assert.js | `lib/assert.js` | expectedException関数（469-575行目） |

**主要処理フロー**:
- **727-729行目**: getActualでfn実行、expectsErrorで検証
- **577-585行目**: getActual関数でtry-catch実行
- **622-673行目**: エラー引数の型判定と検証ロジック
- **469-575行目**: RegExp、Error、検証関数への対応

#### Step 5: 非同期アサーション関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | assert.js | `lib/assert.js` | Assert.prototype.rejects（737-739行目） |
| 5-2 | assert.js | `lib/assert.js` | waitForActual関数（597-620行目） |

**主要処理フロー**:
- **737-739行目**: async関数としてPromise/関数の結果を待機
- **597-620行目**: Promise/関数の実行と例外捕捉

### プログラム呼び出し階層図

```
lib/assert.js
    │
    ├─ assert() / Assert.prototype.ok() [185-198行目]
    │      └─ innerOk() (internal/assert/utils)
    │
    ├─ Assert.prototype.strictEqual() [355-369行目]
    │      └─ Object.is()
    │      └─ innerFail() (internal/assert/utils)
    │
    ├─ Assert.prototype.deepStrictEqual() [305-320行目]
    │      └─ isDeepStrictEqual() (internal/util/comparisons)
    │      └─ innerFail()
    │
    ├─ Assert.prototype.throws() [727-729行目]
    │      ├─ getActual() [577-585行目]
    │      └─ expectsError() [622-673行目]
    │              └─ expectedException() [469-575行目]
    │
    ├─ Assert.prototype.rejects() [737-739行目]
    │      ├─ waitForActual() [597-620行目]
    │      └─ expectsError()
    │
    └─ Assert.prototype.match() [861-863行目]
           └─ internalMatch() [822-852行目]
```

### データフロー図

```
[入力]               [処理]                    [出力]

value ───▶ assert.ok ───▶ void / AssertionError
actual, expected ───▶ strictEqual ───▶ void / AssertionError
actual, expected ───▶ deepStrictEqual ───▶ void / AssertionError
fn, error ───▶ throws ───▶ void / AssertionError
promise, error ───▶ rejects ───▶ void / AssertionError
string, regexp ───▶ match ───▶ void / AssertionError
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| assert.js | `lib/assert.js` | ソース | メインモジュール |
| internal/assert/assertion_error.js | `lib/internal/assert/assertion_error.js` | ソース | AssertionErrorクラス |
| internal/assert/utils.js | `lib/internal/assert/utils.js` | ソース | innerOk、innerFail等 |
| internal/util/comparisons.js | `lib/internal/util/comparisons.js` | ソース | 深い比較アルゴリズム |
| internal/util/inspect.js | `lib/internal/util/inspect.js` | ソース | オブジェクト検査 |
| internal/validators.js | `lib/internal/validators.js` | ソース | バリデーション |
