diff --git a/GFramework.Core.Tests/Architectures/TestCommandWithResultV2.cs b/GFramework.Core.Tests/Architectures/TestCommandWithResultV2.cs index 8e04fc34..571ab4d9 100644 --- a/GFramework.Core.Tests/Architectures/TestCommandWithResultV2.cs +++ b/GFramework.Core.Tests/Architectures/TestCommandWithResultV2.cs @@ -11,7 +11,7 @@ public sealed class TestCommandWithResultV2 : ICommand private IArchitectureContext _context = null!; /// - /// 获取或设置命令执行结果。 + /// 获取命令执行结果;该值只能在对象初始化阶段设置。 /// public int Result { get; init; } diff --git a/GFramework.Core.Tests/Architectures/TestQueryV2.cs b/GFramework.Core.Tests/Architectures/TestQueryV2.cs index 59e6020c..f95c2300 100644 --- a/GFramework.Core.Tests/Architectures/TestQueryV2.cs +++ b/GFramework.Core.Tests/Architectures/TestQueryV2.cs @@ -11,7 +11,7 @@ public sealed class TestQueryV2 : IQuery private IArchitectureContext _context = null!; /// - /// 获取或设置查询返回值。 + /// 获取查询返回值;该值只能在对象初始化阶段设置。 /// public int Result { get; init; } diff --git a/GFramework.Core.Tests/Architectures/TrackingPipelineBehavior.cs b/GFramework.Core.Tests/Architectures/TrackingPipelineBehavior.cs index 6caebc50..a9148e96 100644 --- a/GFramework.Core.Tests/Architectures/TrackingPipelineBehavior.cs +++ b/GFramework.Core.Tests/Architectures/TrackingPipelineBehavior.cs @@ -1,3 +1,4 @@ +using System.Threading; using GFramework.Cqrs.Abstractions.Cqrs; namespace GFramework.Core.Tests.Architectures; @@ -10,13 +11,20 @@ namespace GFramework.Core.Tests.Architectures; public sealed class TrackingPipelineBehavior : IPipelineBehavior where TRequest : IRequest { - /// - /// 获取当前测试进程中该请求类型对应的行为触发次数。 - /// - public static int InvocationCount { get; set; } + private static int _invocationCount; /// - /// 记录一次行为执行,然后继续执行下一个处理器。 + /// 获取当前测试进程中该请求类型对应的行为触发次数。 + /// 该计数器是按泛型闭包共享的静态状态,测试需要在每次运行前显式重置。 + /// + public static int InvocationCount + { + get => Volatile.Read(ref _invocationCount); + set => Volatile.Write(ref _invocationCount, value); + } + + /// + /// 以线程安全方式记录一次行为执行,然后继续执行下一个处理器。 /// /// 当前请求消息。 /// 下一个处理委托。 @@ -27,7 +35,7 @@ public sealed class TrackingPipelineBehavior : IPipelineBeh MessageHandlerDelegate next, CancellationToken cancellationToken) { - InvocationCount++; + Interlocked.Increment(ref _invocationCount); return await next(message, cancellationToken).ConfigureAwait(false); } } diff --git a/GFramework.Core.Tests/Coroutine/ComplexQuery.cs b/GFramework.Core.Tests/Coroutine/ComplexQuery.cs index bb58ec3f..69418cd8 100644 --- a/GFramework.Core.Tests/Coroutine/ComplexQuery.cs +++ b/GFramework.Core.Tests/Coroutine/ComplexQuery.cs @@ -43,7 +43,8 @@ internal class ComplexQuery : IQuery /// 此前通过 绑定的上下文实例。 public IArchitectureContext GetContext() { - return _context!; + return _context ?? throw new InvalidOperationException( + $"{nameof(SetContext)} must be called before {nameof(GetContext)}."); } /// diff --git a/GFramework.Core.Tests/Coroutine/TestTimeSource.cs b/GFramework.Core.Tests/Coroutine/TestTimeSource.cs index a7d9a185..9a62c954 100644 --- a/GFramework.Core.Tests/Coroutine/TestTimeSource.cs +++ b/GFramework.Core.Tests/Coroutine/TestTimeSource.cs @@ -5,7 +5,7 @@ namespace GFramework.Core.Tests.Coroutine; /// /// 为协程测试提供固定时间步长的时间源。 /// -public class TestTimeSource : ITimeSource +public sealed class TestTimeSource : ITimeSource { /// /// 获取当前累计时间。 diff --git a/GFramework.Core.Tests/Environment/EnvironmentTests.cs b/GFramework.Core.Tests/Environment/EnvironmentTests.cs index a6b59bd3..79f9cfc2 100644 --- a/GFramework.Core.Tests/Environment/EnvironmentTests.cs +++ b/GFramework.Core.Tests/Environment/EnvironmentTests.cs @@ -49,7 +49,7 @@ public class EnvironmentTests [Test] public void Get_Should_Return_Value_When_Key_Exists() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.Get("testKey"); @@ -73,7 +73,7 @@ public class EnvironmentTests [Test] public void Get_Should_ReturnNull_When_Type_Does_Not_Match() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.Get>("testKey"); @@ -86,7 +86,7 @@ public class EnvironmentTests [Test] public void TryGet_Should_ReturnTrue_And_Value_When_Key_Exists() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.TryGet("testKey", out var value); @@ -112,7 +112,7 @@ public class EnvironmentTests [Test] public void TryGet_Should_ReturnFalse_When_Type_Does_Not_Match() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.TryGet>("testKey", out var value); @@ -126,7 +126,7 @@ public class EnvironmentTests [Test] public void GetRequired_Should_Return_Value_When_Key_Exists() { - _environment.Register("testKey", "testValue"); + _environment.RegisterForTest("testKey", "testValue"); var result = _environment.GetRequired("testKey"); @@ -149,7 +149,7 @@ public class EnvironmentTests [Test] public void Register_Should_Add_Value_To_Dictionary() { - _environment.Register("newKey", "newValue"); + _environment.RegisterForTest("newKey", "newValue"); var result = _environment.Get("newKey"); @@ -162,8 +162,8 @@ public class EnvironmentTests [Test] public void Register_Should_Overwrite_Existing_Value() { - _environment.Register("testKey", "value1"); - _environment.Register("testKey", "value2"); + _environment.RegisterForTest("testKey", "value1"); + _environment.RegisterForTest("testKey", "value2"); var result = _environment.Get("testKey"); diff --git a/GFramework.Core.Tests/Environment/TestEnvironment.cs b/GFramework.Core.Tests/Environment/TestEnvironment.cs index 08d5ee8c..10ce3c0c 100644 --- a/GFramework.Core.Tests/Environment/TestEnvironment.cs +++ b/GFramework.Core.Tests/Environment/TestEnvironment.cs @@ -5,7 +5,7 @@ namespace GFramework.Core.Tests.Environment; /// /// 为环境相关测试提供可写注册入口的测试环境实现。 /// -public class TestEnvironment : EnvironmentBase +public sealed class TestEnvironment : EnvironmentBase { /// /// 获取测试环境名称。 @@ -13,11 +13,11 @@ public class TestEnvironment : EnvironmentBase public override string Name { get; } = "TestEnvironment"; /// - /// 将测试数据注册到基础环境存储中,便于测试通过公开入口准备上下文。 + /// 将测试数据注册到基础环境存储中,便于测试通过显式测试辅助入口准备上下文。 /// /// 要注册的环境键。 /// 要注册的环境值。 - public new void Register(string key, object value) + public void RegisterForTest(string key, object value) { base.Register(key, value); } diff --git a/GFramework.Core.Tests/Query/AbstractAsyncQueryTests.cs b/GFramework.Core.Tests/Query/AbstractAsyncQueryTests.cs index 305c5f0d..6a0edde2 100644 --- a/GFramework.Core.Tests/Query/AbstractAsyncQueryTests.cs +++ b/GFramework.Core.Tests/Query/AbstractAsyncQueryTests.cs @@ -212,7 +212,7 @@ public class AbstractAsyncQueryTests Assert.That(result, Is.Not.Null); Assert.That(result.Value, Is.EqualTo(20)); - Assert.That(result.DoubleValue, Is.EqualTo(30)); + Assert.That(result.TripleValue, Is.EqualTo(30)); } /// diff --git a/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs b/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs index 574f5bc8..06844ab0 100644 --- a/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs +++ b/GFramework.Core.Tests/Query/AsyncQueryExecutorTests.cs @@ -87,7 +87,7 @@ public class AsyncQueryExecutorTests Assert.That(result, Is.Not.Null); Assert.That(result.Value, Is.EqualTo(200)); - Assert.That(result.DoubleValue, Is.EqualTo(300)); + Assert.That(result.TripleValue, Is.EqualTo(300)); } /// diff --git a/GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs b/GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs index 8c0f5e35..ca575a3c 100644 --- a/GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs +++ b/GFramework.Core.Tests/Query/TestAsyncComplexQuery.cs @@ -25,7 +25,7 @@ public sealed class TestAsyncComplexQuery : AbstractAsyncQuery - /// 获取或设置查询值。 + /// 获取查询值;该值只能在对象初始化阶段设置。 /// public int Value { get; init; } } diff --git a/GFramework.Core.Tests/Query/TestAsyncQueryResult.cs b/GFramework.Core.Tests/Query/TestAsyncQueryResult.cs index 93f2b262..ea156ef4 100644 --- a/GFramework.Core.Tests/Query/TestAsyncQueryResult.cs +++ b/GFramework.Core.Tests/Query/TestAsyncQueryResult.cs @@ -6,12 +6,12 @@ namespace GFramework.Core.Tests.Query; public sealed class TestAsyncQueryResult { /// - /// 获取或设置主结果值。 + /// 获取主结果值;该值只能在对象初始化阶段设置。 /// public int Value { get; init; } /// - /// 获取或设置派生的双重结果值。 + /// 获取派生的三倍结果值;该值只能在对象初始化阶段设置。 /// - public int DoubleValue { get; init; } + public int TripleValue { get; init; } } diff --git a/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs b/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs index 068b2a66..91174cef 100644 --- a/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs +++ b/GFramework.Core.Tests/Query/TestAsyncQueryResultV2.cs @@ -6,12 +6,12 @@ namespace GFramework.Core.Tests.Query; public sealed class TestAsyncQueryResultV2 { /// - /// 获取或设置值 + /// 获取值;该值只能在对象初始化阶段设置。 /// public int Value { get; init; } /// - /// 获取或设置双倍值 + /// 获取三倍值;该值只能在对象初始化阶段设置。 /// - public int DoubleValue { get; init; } + public int TripleValue { get; init; } } diff --git a/GFramework.Core.Tests/State/StateMachineTests.cs b/GFramework.Core.Tests/State/StateMachineTests.cs index 135e242d..f8fbf2c6 100644 --- a/GFramework.Core.Tests/State/StateMachineTests.cs +++ b/GFramework.Core.Tests/State/StateMachineTests.cs @@ -245,7 +245,7 @@ public class StateMachineTests [Test] public async Task ChangeToAsync_WhenCurrentStateDeniesTransition_WithAsyncState_Should_Call_CanTransitionToAsync() { - var state1 = new TestAsyncState { AllowTransition = false }; + var state1 = new TestAsyncState { AllowTransitions = false }; var state2 = new TestStateV3(); _stateMachine.Register(state1); _stateMachine.Register(state2); diff --git a/GFramework.Core.Tests/State/TestAsyncState.cs b/GFramework.Core.Tests/State/TestAsyncState.cs index af31b698..558afad3 100644 --- a/GFramework.Core.Tests/State/TestAsyncState.cs +++ b/GFramework.Core.Tests/State/TestAsyncState.cs @@ -10,7 +10,7 @@ public sealed class TestAsyncState : IState, IAsyncState /// /// 获取或设置是否允许向目标状态转移。 /// - public bool AllowTransition { get; set; } = true; + public bool AllowTransitions { get; set; } = true; /// /// 获取异步进入状态是否已被调用。 @@ -80,7 +80,7 @@ public sealed class TestAsyncState : IState, IAsyncState { await Task.Delay(1).ConfigureAwait(false); CanTransitionToCallCount++; - return AllowTransition; + return AllowTransitions; } /// diff --git a/GFramework.Core.Tests/State/TestStateMachineSystemV5.cs b/GFramework.Core.Tests/State/TestStateMachineSystemV5.cs index f5c83853..9b80dfd6 100644 --- a/GFramework.Core.Tests/State/TestStateMachineSystemV5.cs +++ b/GFramework.Core.Tests/State/TestStateMachineSystemV5.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using GFramework.Core.Abstractions.State; using GFramework.Core.State; @@ -14,8 +15,8 @@ public class TestStateMachineSystemV5 : StateMachineSystem /// 获取状态机当前维护的状态实例映射,供测试断言注册结果使用。 /// /// 状态类型到状态实例的只读视图。 - public IDictionary GetStates() + public IReadOnlyDictionary GetStates() { - return States; + return States as IReadOnlyDictionary ?? new ReadOnlyDictionary(States); } } diff --git a/GFramework.Core.Tests/State/TestStateV5_2.cs b/GFramework.Core.Tests/State/TestStateV5_2.cs index 09a4e2a1..190864ce 100644 --- a/GFramework.Core.Tests/State/TestStateV5_2.cs +++ b/GFramework.Core.Tests/State/TestStateV5_2.cs @@ -19,6 +19,7 @@ public class TestStateV5_2 : IState /// 始终返回 以简化状态机切换测试。 public bool CanTransitionTo(IState next) { + _ = next; return true; } @@ -28,6 +29,7 @@ public class TestStateV5_2 : IState /// 前一个状态。 public void OnEnter(IState? previous) { + _ = previous; } /// @@ -36,5 +38,6 @@ public class TestStateV5_2 : IState /// 下一个状态。 public void OnExit(IState? next) { + _ = next; } } diff --git a/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs b/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs index aa0fe622..da01d06a 100644 --- a/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs +++ b/GFramework.Core.Tests/Utility/AbstractContextUtilityTests.cs @@ -198,7 +198,7 @@ public class AbstractContextUtilityTests Assert.That(utility.Destroyed, Is.True); // 重置状态 - utility.Destroyed = false; + utility.ResetDestroyedStateForTest(); // 第二次初始化和销毁 utility.Initialize(); diff --git a/GFramework.Core.Tests/Utility/TestContextUtilityV1.cs b/GFramework.Core.Tests/Utility/TestContextUtilityV1.cs index 370c8d77..9140ee72 100644 --- a/GFramework.Core.Tests/Utility/TestContextUtilityV1.cs +++ b/GFramework.Core.Tests/Utility/TestContextUtilityV1.cs @@ -14,12 +14,13 @@ public sealed class TestContextUtilityV1 : AbstractContextUtility public bool Initialized { get; private set; } /// - /// 获取或设置一个值,该值指示当前工具是否已执行销毁逻辑。 + /// 获取一个值,该值指示当前工具是否已执行销毁逻辑。 /// - public bool Destroyed { get; set; } + public bool Destroyed { get; private set; } /// - /// 获取一个值,该值指示测试初始化钩子是否已被调用。 + /// 获取一个值,该值指示测试专用的 钩子是否已被调用。 + /// 该标记与 共享同一执行时机,但单独暴露以便断言钩子本身已运行。 /// public bool InitCalled { get; private set; } @@ -48,4 +49,12 @@ public sealed class TestContextUtilityV1 : AbstractContextUtility { Destroyed = true; } + + /// + /// 重置销毁标记,供同一实例的重复生命周期测试在下一轮初始化前清理观测状态。 + /// + public void ResetDestroyedStateForTest() + { + Destroyed = false; + } } diff --git a/GFramework.Core.Tests/Utility/TestContextUtilityV2.cs b/GFramework.Core.Tests/Utility/TestContextUtilityV2.cs index ce683b1e..d52d7067 100644 --- a/GFramework.Core.Tests/Utility/TestContextUtilityV2.cs +++ b/GFramework.Core.Tests/Utility/TestContextUtilityV2.cs @@ -13,9 +13,9 @@ public sealed class TestContextUtilityV2 : AbstractContextUtility public bool Initialized { get; private set; } /// - /// 获取或设置一个值,该值指示当前工具是否已执行销毁逻辑。 + /// 获取一个值,该值指示当前工具是否已执行销毁逻辑。 /// - public bool Destroyed { get; set; } + public bool Destroyed { get; private set; } /// /// 获取一个值,该值指示自定义初始化步骤是否已完成。 diff --git a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md index e0876fca..13d194c0 100644 --- a/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md +++ b/ai-plan/public/analyzer-warning-reduction/todos/analyzer-warning-reduction-tracking.md @@ -6,10 +6,11 @@ ## 当前恢复点 -- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-085` -- 当前阶段:`Phase 85` +- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-086` +- 当前阶段:`Phase 86` - 当前焦点: - `2026-04-27` 已按 `$gframework-batch-boot 100` 连续执行多波 `MA0048` 小切片,当前以 `GFramework.Core.Tests` 的测试辅助类型拆分为主 + - `2026-04-27` 已按 `$gframework-pr-review` 收敛 `PR #298` 的有效 nitpick,修复测试辅助类型的只读暴露、线程安全、空安全与文档一致性问题 - 本轮已完成 `ArchitectureContextTests`、`AsyncQueryExecutorTests`、`CommandExecutorTests`、`StateTests`、`StateMachineTests`、`StateMachineSystemTests`、`ArchitectureModulesBehaviorTests`、`ArchitectureAdditionalCqrsHandlersTests`、`QueryCoroutineExtensionsTests`、`ObjectPoolTests`、`AbstractContextUtilityTests` 等低风险单文件切片 - 当前仓库根权威基线已从 `353 Warning(s)` / `279` 个唯一位点下降到 `288 Warning(s)` / `214` 个唯一位点 - 当前分支下一波更适合转向 `GameContextTests.cs`、`ArchitectureServicesTests.cs`、`RegistryInitializationHookBaseTests.cs` 这类仍在 `GFramework.Core.Tests` 内、但已混入 `CS8766` / `MA0016` 的小型混合切片 @@ -19,15 +20,15 @@ - 当前 `origin/main` 基线提交为 `7cfdd2c`(`2026-04-27T16:59:57+08:00`)。 - 当前直接验证结果: - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - - 最新结果:成功;`0 Warning(s)`、`0 Error(s)` + - 最新结果:成功;`28 Warning(s)`、`0 Error(s)`;当前 warning 来自 `GameContextTests.cs`、`ArchitectureServicesTests.cs`、`RegistryInitializationHookBaseTests.cs` 等既有热点 + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build` + - 最新结果:成功;`1610` 通过、`0` 失败 - `dotnet clean` - 最新结果:成功;已刷新仓库根 non-incremental 基线 - `dotnet build` - 最新结果:成功;`288 Warning(s)`、`0 Error(s)`,唯一位点 `214` - `dotnet build GFramework.Game/GFramework.Game.csproj -c Release` - 最新结果:成功;`0 Warning(s)`、`0 Error(s)` - - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` - - 最新结果:成功;`0 Warning(s)`、`0 Error(s)` - `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release --filter "FullyQualifiedName~YamlConfigLoaderTests.ReadYamlAsync_Should_Preserve_OperationCanceledException_When_Cancellation_Is_Requested"` - 最新结果:成功;`1` 通过、`0` 失败 - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --filter "FullyQualifiedName~MicrosoftDiContainerTests.GetAllByPriority_Should_Sort_By_Priority_Ascending"` diff --git a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md index 13a7b22c..b57f4b67 100644 --- a/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md +++ b/ai-plan/public/analyzer-warning-reduction/traces/analyzer-warning-reduction-trace.md @@ -1,5 +1,29 @@ # Analyzer Warning Reduction 追踪 +## 2026-04-27 — RP-086 + +### 阶段:收敛 PR #298 的 CodeRabbit nitpick follow-up + +- 触发背景: + - 用户再次执行 `$gframework-pr-review` 后,要求按 `PR #298` 的 nitpick comments 收敛仍然适用的问题 + - 复核 PR 真值后确认当前分支无 failed checks、无 open review threads,但仍有一批测试辅助类型的可维护性 nitpick 值得本地落地 +- 主线程实施: + - 校验 `TestStateMachineSystemV5`、`ComplexQuery`、`TrackingPipelineBehavior`、`TestEnvironment`、`TestContextUtilityV1/V2` 等改动后,分别修复可变内部状态暴露、`_context!` 空抑制、静态计数器非原子递增、`new Register(...)` 测试辅助入口和生命周期标记公开 setter 问题 + - 统一更新 `TestQueryV2`、`TestCommandWithResultV2`、`TestAsyncQueryInput`、`TestAsyncQueryResult*` 的 XML 文档,使 `init` 属性语义与文档一致 + - 将三倍结果属性从 `DoubleValue` 更名为 `TripleValue`,同步更新 `TestAsyncComplexQuery*` 与相关断言,避免名称与 `* 3` 的行为不一致 + - 精简 active tracking,移除重复的 `GFramework.Core.Tests` Release build 记录,并把该项目的当前真值修正为 `28 Warning(s)` +- 验证里程碑: + - `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release` + - 结果:成功;`28 Warning(s)`、`0 Error(s)` + - `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build` + - 结果:成功;`1610` 通过、`0` 失败 +- 当前结论: + - `PR #298` 中仍然适用的低风险 nitpick 已完成收敛,且没有为当前 touched files 引入新的构建 warning 或测试回归 + - `GFramework.Core.Tests` 的剩余 warning 仍集中在 `GameContextTests.cs`、`ArchitectureServicesTests.cs`、`RegistryInitializationHookBaseTests.cs` 等既有热点,不属于本轮 nitpick follow-up 新引入问题 +- 下一步: + 1. 提交本轮 `PR #298` nitpick follow-up 与 `ai-plan` 同步。 + 2. 回到 `GameContextTests.cs` / `ArchitectureServicesTests.cs` 的 `CS8766` warning reduction 主线。 + ## 2026-04-27 — RP-085 ### 阶段:按 `$gframework-batch-boot 100` 并行消化 `GFramework.Core.Tests` 低风险 `MA0048`