The Standard Testing について
The Standard Testingは、The Standardに沿って構築されたソフトウェア向けのテストスキルです。TDD、検証、例外、サービス、コントローラー、UIのテスト手法に加え、テスト順序と規約を定めます。
主な機能
- 01失敗から始めるTDD手順
- 02検証テストとストレージ制約の整合
- 03サービスごとのテスト責務
- 04コントローラーとエンドポイントのテスト
- 05UIコンポーネントのテスト指針
- 06テスト構成と命名規約
活用シーン
- 01サービスルーチンの新規テスト計画
- 02基盤層の検証とストレージ制約の照合
- 03例外マッピングと依存呼び出しのテスト
- 04コントローラーとUIコンポーネントのテスト整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hassanhabib/ the-standard-skills --skill the-standard-testingインストール後、Claude Code で/the-standard-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
manifest.jsoncontracts/contracts.jsonexamples/bad/example_bad_test.csexamples/good/example_validation_test.csexample_foundation_test.csrules/rules.jsonrules.mdtemplates/service_test_template.cstest_class_root_template.cstemplates/controllers/acceptance/controller_acceptance_test_class_root_template.cscontroller_acceptance_test_template.cstemplates/controllers/unit/controller_unit_test_class_root_template.cscontroller_unit_test_template.cstemplates/foundations/foundation_service_test_template.csfoundation_test_class_root_template.cstemplates/processings/processing_service_test_template.csprocessing_test_class_root_template.csvalidations/anti-patterns.mdchecklist.md詳細
The Standard のテスト
このスキルについて
このスキルでは、The Standard のテスト、検証、および証明の方法を定めます。 テスト駆動開発、検証戦略、例外マッピング、単体テストの構成、コントローラーテスト、UI コンポーネントテストを扱います。
明示的な対象範囲
このスキルでは、以下を明示的に扱います。
- Services 章に記載された Foundation サービスの実装および検証/テストのパターン
- 構造、ロジック、外部要因、依存関係に関する検証テスト
- 例外マッピングとカテゴリーテスト
- Processing サービスのテスト責務
- Orchestration サービスの呼び出し順序テスト
- Aggregation サービスのテスト制限
- REST コントローラーの単体テストと受け入れテスト
- ベース、コアコンポーネント、ページの UI コンポーネントテスト
- 提供された実装仕様のうち、単体テスト、一部のテスト構成、規約、AAA、テスト順序に関するセクション
- テストの作成と実装の検証に関わる TDD の FAIL/PASS 規律
使用するタイミング
テストの作成、レビュー、拡張、修正、または実施順序の決定を行う際は、常にこのスキルを使用してください。 何を最初にテストするか、テスト内で例外をどのようにマッピングするか、Standard に準拠したフローをどのように証明するかを判断する際にも使用してください。
テストの基本原則
- TDD に従います。
- 最初に失敗するテストを書きます。
- テストが実際に失敗することを確認します。
- テストに合格するために必要な最小限の実装を行います。
- 関連するテストスイート全体が合格することを確認します。
- 動作を変更せずにリファクタリングします。
- これを繰り返します。
検証テストのルール
検証の信頼できる情報源
-
検証ルールは、権威あるすべての情報源から推定しなければなりません。
- Foundation サービスのビジネスルール
- ストレージ層の構成(
StorageBroker.[Entity].Configurations.cs) - 使用方法から推測されるドメイン上の要件
-
ストレージ構成は、適用される制約の最小要件を表します。
- 必須か任意か
- 最大長
- 最小長(構成されている場合)
- 精度/スケール/形式(該当する場合)
-
Foundation サービスは、制約の適用境界を担います。
- 永続化エラーの原因となるすべての制約は、ストレージに到達する前に検証しなければなりません。
- 決定論的に可能な場合は、検証によってデータベース例外を防止しなければなりません。
検証の整合性ルール
-
Foundation の検証は、ストレージの制約と同等以上に厳格でなければなりません。
-
以下は許可されます(強化ルール)。
- ストレージ:任意 → Foundation:必須
- ストレージ:任意 → Foundation:制約あり(最小/最大長)
- ストレージ:最大長 → Foundation:より短い最大長
-
以下は許可されません(制約の緩和または欠落)。
- ストレージ:必須 → Foundation:必須として検証しない
- ストレージ:最大長 → Foundation:長さを検証しない
-
整合性違反は、以下として扱わなければなりません。
- 設計上の欠陥
- テストの失敗条件
- レビューの阻害要因
検証責務のルール
-
以下の適用をデータベースに依存してはなりません。
- 必須フィールドの検証
- 長さの検証
- 形式の検証
-
事前検証なしでデータベースが適用してよい制約は、以下に限られます。
- 外部キー制約
- 一意性/重複キー制約
- 同時実行制約
-
Foundation サービスで決定論的に実施できる検証は、そこで必ず実施しなければなりません
ストレージ構成からの検証テストの導出
-
ストレージ構成(
StorageBroker.[Entity].Configurations.cs)で定義するのは制約であり、検証の動作ではありません。 -
ストレージ構成で定義された制約ごとに、Foundation サービスに対応する検証ルールが MUST 存在します。
- 必須フィールド
- 長さの制約(最小/最大)
- 該当する場合は、精度/形式の制約
-
検証テストは MUST 以下を満たすものとします。
- Foundation サービスの検証メソッドのみを対象とする
- ストレージ構成の動作を直接テストしない
- ストレージで定義された各制約が Foundation 層で適用されることを証明する
-
各プロパティの制約について、検証テストは制約違反と境界超過に焦点を当てる MUST ものとします。
-
無効なケース(制約に違反)→ FAIL
- 必須フィールドがない/null
- 値が最大長を超える
- 値が最小長を下回る(該当する場合)
-
境界違反のケース:
- 最大長をわずかに超える → FAIL
- 最小長をわずかに下回る → FAIL(該当する場合)
-
-
許容範囲内の有効なシナリオはロジックテストでカバーし、検証テストで重複してテストしてはなりません。
-
ストレージ構成と Foundation の検証の不整合は、以下として扱う MUST ものとします。
- 設計上の欠陥
- テスト失敗の条件
- レビューのブロッカー
-
自動化により制約の特定を支援してもかまいません(例:EF メタデータを使用)。ただし、以下の条件があります。
- 生成されたテストは、Foundation の動作を引き続き検証する MUST
- 自動化によって、データベース層を直接検証するテストを作成してはならない
-
すべての検証テストは MUST 以下を満たすものとします。
- 標準の命名規則に従う
- 明示的で、意図が伝わるものにする
検証の順序
- まず構造検証を行います。
- 次に論理検証を行います。
- その次に外部検証を行います。
- 外部リソースが失敗の原因である場合は、依存関係の検証を行います。
サーキットブレーカー検証
- null チェックやその他の即時停止ガードでは、直ちに処理を中断する必要があります。
- 処理を続けると無効な参照や意味のない処理が発生する場合は、直ちに停止します。
継続的な検証
- 複数のフィールドがそれぞれ独立して無効になり得る場合は、例外をスローする前にそれらを収集します。
- アップサート可能な例外データを使用します。
- 条件とメッセージを含む動的なルールを使用します。
- 検証コレクターのルーチンを使用します。
- コレクターにエラーが含まれている場合に一度だけ例外をスローします。
ハイブリッド継続的検証
- 子プロパティを検証する前に、親オブジェクトを検証します。
- 意図しない null 参照エラーを避けるため、ネストされた検証をレベルごとに分割します。
Foundation サービスのテスト規則
- まず正常系をテストします。
- 次に構造検証をテストします。
- 次に論理検証をテストします。
- 次に外部検証をテストします。
- 次に依存関係の検証をテストします。
- 次に依存関係の例外をテストします。
- 次にサービスの例外をテストします。
- 常にログ記録とブローカー呼び出しを検証します。
- 望ましくない呼び出しが発生していないことを常に検証します。
- 検証と例外の動作を常にその場で明示します。
Processing サービスのテスト規則
- プリミティブなブローカーの詳細ではなく、高次のロジックをテストします。
- Processing サービスが使用する内容のみを検証します。
- 変換処理をテストします。
- 例:オブジェクト → bool またはオブジェクト → 件数
- 組み合わせをテストします。
- 例:取得+追加、取得+変更、存在確認、アップサート
- Foundation の例外から Processing の例外へのマッピングをテストします。
Orchestration サービスのテスト規則
- 複数エンティティのフローの組み合わせをテストします。
- 存在する場合は、コントラクト間のマッピング/分岐をテストします。
- フローが順序に依存する場合は、呼び出し順序をテストします。
- 入出力によって順序が決まる場合は、自然な順序を優先します。
- 順序が自然に決まらない場合は、明示的な順序検証を使用します。
- オーケストレーションレベルの例外のラップとアンラップを検証します。
- 依存関係の形状と結果の動作を通じて、正規化の結果を間接的にテストします。
集約サービスのテストルール
- 集約サービスでは、依存先呼び出しの順序をテストしないでください。
- 集約サービスでは、モックの呼び出し順を検証する形式のアサーションを使用しないでください。
- 基本的な構造検証と、公開レベルの集約動作のみをテストしてください。
- 集約サービスは複数回呼び出したり、単純に受け渡したりする場合があります。オーケストレーションロジックではなく、契約と公開される抽象化をテストしてください。
コントローラーとプロトコルのテストルール
- コントローラーには、マッピングロジックのユニットテストが必要です。
- 成功コードのマッピングをユニットテストしてください。
- 検証エラー/依存先エラー/サービスエラーのマッピングをユニットテストしてください。
- セキュリティ、つまり認可/認証失敗のマッピングをユニットテストしてください。
- すべてのエンドポイントを受け入れテストしてください。
- 受け入れテスト後にテストデータをクリーンアップしてください。
- 受け入れテストの実行時には、マイクロサービスが所有していない外部リソースをエミュレートしてください。
- ユニットテストと受け入れテストに加えて、統合テストとエンドツーエンドテストも有効です。
UI コンポーネントのテストルール
基底コンポーネント
- 基底コンポーネントは薄いラッパーとして扱ってください。
- 必要に応じて、公開 API とラッパーの動作をテストしてください。
- 基底コンポーネントにビジネスロジックを含めないでください。
コアコンポーネント
- コアコンポーネントはテスト駆動で開発します。
- 要素をテストしてください。
- 存在
- プロパティ
- アクション
- 存在は、プロパティの割り当て、id による検索、または一般的な検索によってテストできます。
- スタイルがコンポーネントの契約に含まれる場合は、スタイルをテストしてください。
- 状態を変更する、コンポーネントを作成する、またはサービス呼び出しをトリガーするアクションをテストしてください。
- コアコンポーネントは、1 つだけのビューサービスと統合してください。
ページ/コンテナー
- ページは、よりシンプルなルートコンテナーです。
- 通常、ユニットテストは必要ありません。
- ビジネスロジックを含めないでください。
提供された実装プロファイルに基づくユニットテストの規約
- テストでは部分クラスの分割を反映してください。
- ルートのテストファイルでセットアップ/ヘルパーを使用してください。
- テストをロジック、検証、例外のファイルに分割してください。
- GWT を使用してください:Given / When / Then。
- すべての依存先をモックしてください。
- 読みやすいアサーションを使用してください。
- 期待値の同一性を保護するため、ディープコピーを使用してください。
- デフォルトでランダムなデータを使用してください。
- 依存先の正確な呼び出しを検証してください。
- 最後に VerifyNoOtherCalls を実行してください。
- 明確でシナリオに基づいた命名にしてください。
基盤サービスの追加ルーチンにおける正確なテスト実装順序
実装プロファイルに基づいて Add{Entity}Async ルーチンを実装する場合は、次の順序に従ってください。
- ShouldAdd{Entity}Async
- ShouldThrowValidationExceptionOnAddIf{Entity}IsNullAndLogItAsync
- ShouldThrowValidationExceptionOnAddIf{Entity}IsInvalidAndLogItAsync
- ShouldThrowDependencyValidationExceptionOnAddIfBadRequestErrorOccursAndLogItAsync
- ShouldThrowDependencyValidationExceptionOnAddIfConflictErrorOccursAndLogItAsync
- ShouldThrowCriticalDependencyExceptionOnAddIfUnauthorizedErrorOccursAndLogItAsync
- ShouldThrowCriticalDependencyExceptionOnAddIfForbiddenErrorOccursAndLogItAsync
- ShouldThrowCriticalDependencyExceptionOnAddIfNotFoundErrorOccursAndLogItAsync
- ShouldThrowCriticalDependencyExceptionOnAddIfUrlNotFoundErrorOccursAndLogItAsync
- ShouldThrowDependencyExceptionOnAddIfInternalServerErrorOccursAndLogItAsync
- ShouldThrowDependencyExceptionOnAddIfServiceUnavailableErrorOccursAndLogItAsync
- ShouldThrowCriticalDependencyExceptionOnAddIfHttpRequestErrorOccursAndLogItAsync
- ShouldThrowServiceExceptionOnAddIfServiceErrorOccursAndLogItAsync
ストレージベースのサービスでは、重複キー、DbUpdate、SQL 例外など、ストレージに相当する例外に置き換えてください。
提供された実装プロファイルに基づくテストと例外/ローカライズの補遺
8. ユニットテスト
ユニットテストでは、The Standard の 部分クラス+3 軸のアプローチに従います。
8.1 テストクラスの構成
各エンティティのテストは、サービスと同じ部分クラスの分割構成にします。
| 部分ファイル | テスト |
|---|---|
{Entity}ServiceTests.cs | セットアップ、モック、ヘルパー(CreateRandom{Entity} など) |
{Entity}ServiceTests.Logic.{Method}.cs | 正常系/成功ケースのテスト |
{Entity}ServiceTests.Validations.{Method}.cs | バリデーション失敗のテスト |
{Entity}ServiceTests.Exceptions.{Method}.cs | 依存関係およびサービス例外のテスト |
8.2 規約
| 規約 | 詳細 |
|---|---|
| モック | Moq — Mock<IStorageBroker>、Mock<IModernApiBroker>、Mock<ILoggingBroker> |
| アサーション | FluentAssertions — Should().BeEquivalentTo() |
| ディープクローン | DeepCloner — 入力/期待値/実際のオブジェクトを分離します |
| データ生成 | Tynamix.ObjectFiller — カスタムプロパティ設定を使用する Filler<{Entity}> |
| 例外の比較 | SameExceptionAs 式ヘルパーによる Xeption.SameExceptionAs() |
| テストの命名 | Should{Action}Async / ShouldThrow{Exception}On{Action}If{Condition}AndLogItAsync |
| 呼び出しの検証 | すべてのテストでブローカーの呼び出し(Times.Once/Times.Never)を検証し、最後に VerifyNoOtherCalls() を実行します |
| テストフレームワーク | xUnit — 単一ケースには [Fact]、パラメーター化されたケースには [Theory] [InlineData] を使用します |
8.3 テストパターン — GWT(Given/When/Then)
// given — build input, configure mocks, construct expected exception
// when — invoke the service method
// then — assert result / exception, verify broker interactions
8.4 テストの実装順序
テストは、以下の厳格な順序で必ず記述し、コミットしてください。この順序により、 各カテゴリが前のカテゴリを基盤として構築されます。
- 正常系 —
ShouldAdd{Entity}Async - 構造的バリデーション — エンティティが null かどうかの確認(
ShouldThrowValidationExceptionOnAddIf{Entity}IsNullAndLogItAsync) - 論理的バリデーション —
[Theory] [InlineData]を使用したプロパティレベルの確認(ShouldThrowValidationExceptionOnAddIf{Entity}IsInvalidAndLogItAsync) - 外部依存関係のバリデーション例外 —
BadRequest→Conflict - 外部クリティカル依存関係の例外 —
Unauthorized→Forbidden→NotFound→UrlNotFound - 外部ノンクリティカル依存関係の例外 —
InternalServerError→ServiceUnavailable - トランスポートレベルの例外 —
HttpRequestException - サービスのキャッチオール例外 —
Exception
ストレージベースのサービスでは、手順 4~7 を対応する SQL/EF 例外(
DuplicateKeyException、DbUpdateException、SqlException)に置き換えます。
ルール — コミット前のテスト検証: 各 FAIL コミットでは、テストが 実際に実行され、失敗することを確認してください。各 PASS コミットでは、 すべてのテストが実行され、成功することを確認してください。テストランナーが 実際に失敗を報告したことを確認せずに、FAIL をコミットしてはいけません。 詳細はセクション 12.1.3 — コミットを参照してください。
9. 主要ライブラリ
| パッケージ | 目的 |
|---|---|
Xeption | データ集約機能を備えた拡張例外 |
EFxceptions | 意味のある例外をスローする EF Core ラッパー |
RESTFulSense | 外部 API ブローカー向け HTTP クライアントラッパー |
Moq | 単体テスト用モックフレームワーク |
FluentAssertions | 読みやすいアサーション構文 |
DeepCloner | テストオブジェクトの値ベースのディープクローン |
Tynamix.ObjectFiller | ランダムなテストデータの生成 |
xunit | 単体テストフレームワーク |
例外処理の原則
0. 範囲
これらのルールは、すべてのサービスレイヤーにおける例外の設計、ローカライズ、分類、伝播、およびテストを規定します。
1. ローカライズ(必須)
- 外部(ローカルではない)例外は、境界(Foundation)で必ずローカライズする必要があります。
- ネイティブ例外(SQL、HTTP、SDK)をサービス境界の外に持ち出してはいけません。
- ローカライズでは、ネイティブ例外をドメイン固有の例外に変換する必要があります。
データの保持(必須)
-
外部例外の関連データはすべて、ローカル例外にコピーする必要があります。
Dataディクショナリ- 制約/検証メタデータ
- 識別子/キー
-
ローカライズされた例外には、このデータを保持する必要があります。これにより、次の状態を確保できます。
- 分類後も、直接の内部例外に検証の詳細がすべて含まれる。
2. 分類
-
すべての例外は、次のいずれかに分類する必要があります。
- Validation
- DependencyValidation
- Dependency
- Service
-
分類によって、上流での処理とエクスポーザーのマッピングが決まります。
3. 伝播(ラップ解除/再ラップ)
各サービスレイヤーは、次の処理を行う必要があります。
- 下流の例外をキャッチする
- 分類済み例外のラップを解除する
- ローカル例外を保持する
- 独自の分類済み例外で再ラップする
これにより、下位レイヤーの関心事が漏れるのを防ぎ、レイヤー間の契約を徹底できます。
4. 内部例外の保持(必須)
- 元のローカル例外は、常に内部例外として保持する必要があります。
- どのレイヤーも、ローカル例外を破棄したり置き換えたりしてはいけません。
これにより、次のことが保証されます。
- トレーサビリティ
- 正確なエクスポーザーのマッピング(例:HTTP Conflict/FailedDependency)
- 検証データの保持
5. レイヤーの責務
Foundation
- 外部例外をローカライズする
- ローカル例外のデータを設定する
- Validation/DependencyValidation/Dependency/Service に分類する
Processing
- 分類済み例外のみを処理する
- foundation の例外型に依存してはいけません
- processing レベルの例外で再ラップする
Orchestration
- すべての依存関係からの例外を処理する
- 型ごとに単一の分類済み例外に統一する
- 内部例外のラップを解除し、保持する
6. すべての例外の捕捉(必須)
- すべてのサービスで、次を実装する必要があります。
catch (Exception)
- ServiceException にマッピングする必要があります。
これにより、未知の障害が漏れるのを防ぎます。
7. ロギング
- 各レイヤーは、再スローする前にログを記録する必要があります
- 分類済み例外のみをログに記録する必要があります
8. テスト
Orchestration の例外テスト
[Theory]を使用することが推奨されます- 1つのテストで複数の依存関係の例外型を網羅する必要があります
- 重複を避ける必要があります
9. 設計意図
これらのルールにより、次のことを実現します。
- 外部システムからの完全な抽象化
- 安定したレイヤー間の契約
- 簡素化されたエクスポーザーロジック
- ローカル例外レベルでの検証情報の完全な可視化
例外処理の相互参照(適用)
検証テストの整合性
-
すべての検証テストは、例外処理の原則に準拠しなければなりません。
- ローカライズを検証しなければなりません(ネイティブ例外が公開されないこと)
- ローカル例外が発生した場合のデータ保持を検証しなければなりません
- 検証例外の内部例外に、エラーの詳細がすべて含まれていることを検証しなければなりません
- 処理サービスレイヤー以降では、依存先からの検証例外および依存先の依存関係の検証例外を [Entity][Layer]DependencyValidationExceptions にラップし直さなければなりません
- 処理サービスレイヤー以降では、依存先からの依存関係例外およびサービス例外を [Entity][Layer]DependencyExceptions にラップし直さなければなりません
-
検証テストでは、次のことをアサートしなければなりません。
- 正しいローカル例外の型
- 正しいカテゴリ別例外の型
- 内部例外に検証データが含まれていること(Data ディクショナリが設定されていること)
基盤例外テスト(適用要件)
-
テストでは、ローカライズを検証しなければなりません。
- ネイティブ例外 → ローカル例外 → カテゴリ別例外
-
テストでは、次のことを検証しなければなりません。
- 外部例外のデータがローカル例外にコピーされること
- ローカル例外が内部例外として保持されること
-
テストでは、次の状態を許容してはなりません。
- ネイティブ例外の漏出
- Data ディクショナリの伝播漏れ
処理例外テスト(適用要件)
-
テストでは、次のことをアサートしなければなりません。
- 処理レベルの例外へのラップし直し
- 内部例外の保持
-
テストでは、次のことを行うことが望ましいです。
[Theory]を使用して、同じ型の複数の依存関係検証例外を1つのテストで検証する[Theory]を使用して、同じ型の複数の依存関係例外を1つのテストで検証する- 1つのテストメソッドで複数のケースを検証し、重複を避ける
オーケストレーション例外テスト(適用要件)
-
テストでは、次のことをアサートしなければなりません。
- オーケストレーションレベルの例外へのラップし直し
- 内部例外(ローカル例外)が保持されること
- カテゴリ別例外がオーケストレーションレベルで置き換えられること
-
テストでは、次のことを行うことが望ましいです。
[Theory]を使用して、同じ型の複数の依存関係検証例外を1つのテストで検証する[Theory]を使用して、同じ型の複数の依存関係例外を1つのテストで検証する- 1つのテストメソッドで複数のケースを検証し、重複を避ける
すべてを捕捉する処理の適用要件
- テストでは、次のことを検証しなければなりません。
- 不明な例外が ServiceException にマッピングされること
- いずれのサービスレイヤーからも生の Exception が漏出しないこと
ログ記録の適用要件
- テストでは、次のことを検証しなければなりません。
- 例外がスローされる前にログが記録されること
- ログに記録される例外がカテゴリ別例外であること
設計の完全性に関するルール
- 例外処理の原則への違反は、次のように扱わなければなりません。
- 設計上の欠陥
- テストの失敗
- レビューの阻害要因