diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b787d9e..99ac4850 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
#### Changed
+- **Test nullable analysis now enforces possible-null returns** — Removed the test project's blanket `CS8603` suppression, promoted that warning through `WarningsAsErrors`, and annotated its reflection helper to preserve a private field's possible `null` value while still asserting the runtime type of non-null values. An architecture test locks the warning configuration; the remaining nullable suppressions stay documented as incremental cleanup targets.
+
- **Report sample synchronization is regression-tested** — Added `GoldenReportSampleConsistencyTests` to compare the ordered configured-normalization tables in both checked-in Markdown and HTML samples with the complete `creator-default` profile plus the sample-only overlap-warning value. The testing guide now distinguishes this cross-artifact consistency check from the structural and generation-determinism coverage in `GoldenFileSnapshotTests`. Affected: `FolderDiffIL4DotNet.Tests/Services/GoldenReportSampleConsistencyTests.cs`, `doc/TESTING_GUIDE.md`. Tests: `MarkdownNormalizationTable_MatchesCreatorDefaultProfile`, `HtmlNormalizationTable_MatchesCreatorDefaultProfile`.
### [2.0.1] - 2026-08-21
@@ -1758,6 +1760,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
#### 変更
+- **テストの nullable 解析で null 戻り値候補を強制** — テストプロジェクト全体の `CS8603` 抑制を削除し、この警告を `WarningsAsErrors` でエラー化しました。reflection helper は private field の `null` 可能性を保持しつつ、非 null 値の実行時型を検証します。architecture test で警告設定を固定し、残る nullable 抑制は段階的な解消対象として文書化しています。
+
- **レポートsample同期を回帰テストで保護** — `GoldenReportSampleConsistencyTests`を追加し、commit済みMarkdown/HTML両sampleの設定済み正規化tableを、順序を含む`creator-default` profile全体およびsample固有のoverlap warning用設定値と比較するようにしました。テストガイドでは、この成果物間の整合性検証と、`GoldenFileSnapshotTests`が担う構造/生成決定論の検証との役割を区別しました。対象: `FolderDiffIL4DotNet.Tests/Services/GoldenReportSampleConsistencyTests.cs`, `doc/TESTING_GUIDE.md`。テスト: `MarkdownNormalizationTable_MatchesCreatorDefaultProfile`, `HtmlNormalizationTable_MatchesCreatorDefaultProfile`。
### [2.0.1] - 2026-08-21
diff --git a/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs b/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs
index 5620fd71..d6dbed06 100644
--- a/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs
+++ b/FolderDiffIL4DotNet.Tests/Architecture/CiAutomationConfigurationTests.cs
@@ -35,6 +35,23 @@ public void DotNetWorkflow_EnforcesCoverageThresholds()
Assert.Contains("--settings coverlet.runsettings", releaseWorkflow, StringComparison.Ordinal);
}
+ ///
+ /// Verifies that the restored possible-null return warning fails test-project builds.
+ /// 復帰させた null 戻り値候補の警告がテストプロジェクトのビルドを失敗させることを検証します。
+ ///
+ [Fact]
+ public void TestProject_EnforcesPossibleNullReturnWarning()
+ {
+ var testProject = File.ReadAllText(
+ GetRepositoryFilePath("FolderDiffIL4DotNet.Tests", "FolderDiffIL4DotNet.Tests.csproj"));
+
+ Assert.Contains(
+ "$(WarningsAsErrors);CS8603",
+ testProject,
+ StringComparison.Ordinal);
+ Assert.DoesNotContain(";CS8603;", testProject, StringComparison.Ordinal);
+ }
+
///
/// Verifies that documentation-only changes still run the main CI workflow.
/// ドキュメントのみの変更でもメイン CI ワークフローが実行されることを検証します。
diff --git a/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj b/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj
index 477b71e4..681408d0 100644
--- a/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj
+++ b/FolderDiffIL4DotNet.Tests/FolderDiffIL4DotNet.Tests.csproj
@@ -5,7 +5,8 @@
false
enable
false
- $(NoWarn);CA1031;CS8600;CS8603;CS8604;CS8605;CS8618;CS8619;CS8620;CS8625;xUnit1012
+ $(WarningsAsErrors);CS8603
+ $(NoWarn);CA1031;CS8600;CS8604;CS8605;CS8618;CS8619;CS8620;CS8625;xUnit1012
diff --git a/FolderDiffIL4DotNet.Tests/Services/ProgressReportServiceTests.cs b/FolderDiffIL4DotNet.Tests/Services/ProgressReportServiceTests.cs
index 723ea753..fd551fc8 100644
--- a/FolderDiffIL4DotNet.Tests/Services/ProgressReportServiceTests.cs
+++ b/FolderDiffIL4DotNet.Tests/Services/ProgressReportServiceTests.cs
@@ -433,11 +433,12 @@ public void Dispose_LogsFinalPhaseElapsed()
Assert.NotNull(phaseLog);
}
- private static T GetPrivateField(object target, string fieldName)
+ private static T? GetPrivateField(object target, string fieldName)
{
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
Assert.NotNull(field);
- return (T)field.GetValue(target);
+ var value = field.GetValue(target);
+ return value is null ? default : Assert.IsType(value);
}
private static T InvokePrivate(object target, string methodName, params object[] args)
diff --git a/doc/TESTING_GUIDE.md b/doc/TESTING_GUIDE.md
index 31200d79..996218fd 100644
--- a/doc/TESTING_GUIDE.md
+++ b/doc/TESTING_GUIDE.md
@@ -236,7 +236,7 @@ Workflow/config files: [`.github/workflows/dotnet.yml`](../.github/workflows/dot
- Some disassembler tests are skipped on Windows using [`[SkippableFact]`](https://github.com/AArnott/Xunit.SkippableFact) + `Skip.If(OperatingSystem.IsWindows(), ...)`, which reports them as **Skipped** in the test runner rather than silently passing. [`RealDisassemblerE2ETests`](../FolderDiffIL4DotNet.Tests/Services/RealDisassemblerE2ETests.cs) is skipped only when the explicit E2E opt-in is absent; once `FOLDERDIFF_RUN_E2E=true` is set, missing or non-runnable [`dotnet-ildasm`](https://www.nuget.org/packages/dotnet-ildasm/) is treated as a test failure rather than a skip.
- Unit tests do not require globally installed real [`dotnet-ildasm`](https://www.nuget.org/packages/dotnet-ildasm/) or [`ilspycmd`](https://www.nuget.org/packages/ilspycmd/) for most scenarios because test doubles are used.
- Avoid adding static mutable test hooks. Prefer constructor injection plus [`DiffExecutionContext`](../Services/DiffExecutionContext.cs) for per-run values.
-- The test project has `enable` enabled but suppresses nullable warnings (`CS8600`, `CS8603`, `CS8604`, `CS8605`, `CS8618`, `CS8619`, `CS8620`, `CS8625`) and `xUnit1012` via `` in the `.csproj`. This is intentional: test code deliberately passes `null` to verify argument validation, null-guard branches, and graceful failure paths. Suppressing these warnings avoids noisy false positives while keeping nullable analysis active for production code.
+- The test project has `enable` enabled and enforces `CS8603` (possible null reference return). It still suppresses nullable warnings (`CS8600`, `CS8604`, `CS8605`, `CS8618`, `CS8619`, `CS8620`, `CS8625`) and `xUnit1012` via `` in the `.csproj`. The remaining suppressions cover test code that deliberately passes `null` to verify argument validation, null-guard branches, and graceful failure paths; they should be removed incrementally as those call sites become explicitly annotated.
## Adding or Updating Tests
@@ -489,7 +489,7 @@ dotnet tool run reportgenerator -reports:"TestResults/**/coverage.cobertura.xml"
- 逆アセンブラ関連の一部テストは Windows では [`[SkippableFact]`](https://github.com/AArnott/Xunit.SkippableFact) + `Skip.If(OperatingSystem.IsWindows(), ...)` によりスキップされます。これにより、テストが「成功」扱いで素通りするのではなく、テストランナー上で**Skipped(スキップ)**として明示的に報告されます。[`RealDisassemblerE2ETests`](../FolderDiffIL4DotNet.Tests/Services/RealDisassemblerE2ETests.cs) は E2E opt-in がない場合のみスキップされ、`FOLDERDIFF_RUN_E2E=true` のときに [`dotnet-ildasm`](https://www.nuget.org/packages/dotnet-ildasm/) が使えなければスキップではなく失敗します。
- 多くの単体テストは実ツールのグローバルインストールを不要とします(テストダブル利用)。
- 静的な可変テストフックは追加せず、実行単位の値はコンストラクタ注入と [`DiffExecutionContext`](../Services/DiffExecutionContext.cs) で渡してください。
-- テストプロジェクトでは `enable` を有効にしていますが、nullable 警告(`CS8600`、`CS8603`、`CS8604`、`CS8605`、`CS8618`、`CS8619`、`CS8620`、`CS8625`)および `xUnit1012` を `.csproj` の `` で抑制しています。これは意図的な設計です:テストコードでは引数バリデーション、null ガード分岐、エラー時の正常動作を検証するために意図的に `null` を渡しています。これらの警告を抑制することで、本番コードの nullable 解析を維持しつつ、テストコードでの誤検知ノイズを回避しています。
+- テストプロジェクトでは `enable` を有効にし、`CS8603`(null 参照を返す可能性)を強制しています。nullable 警告(`CS8600`、`CS8604`、`CS8605`、`CS8618`、`CS8619`、`CS8620`、`CS8625`)および `xUnit1012` は引き続き `.csproj` の `` で抑制しています。残る抑制は、引数バリデーション、null ガード分岐、エラー時の正常動作を検証するために意図的に `null` を渡すテストコードを含みます。各呼び出し箇所の意図をアノテーションで明示しながら段階的に削除してください。
## テスト追加・更新時の方針