mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
fix(core-tests): 收敛PR298的nitpick问题
- 修复测试辅助类型的只读暴露、空安全和线程安全问题 - 更新异步查询结果命名与init属性XML文档,保持语义一致 - 同步ai-plan恢复点与验证真值,记录PR298 nitpick跟进
This commit is contained in:
parent
f0a36de07c
commit
fbf8f9f0a2
@ -11,7 +11,7 @@ public sealed class TestCommandWithResultV2 : ICommand<int>
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置命令执行结果。
|
||||
/// 获取命令执行结果;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Result { get; init; }
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ public sealed class TestQueryV2 : IQuery<int>
|
||||
private IArchitectureContext _context = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置查询返回值。
|
||||
/// 获取查询返回值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Result { get; init; }
|
||||
|
||||
|
||||
@ -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<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IRequest<TResponse>
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前测试进程中该请求类型对应的行为触发次数。
|
||||
/// </summary>
|
||||
public static int InvocationCount { get; set; }
|
||||
private static int _invocationCount;
|
||||
|
||||
/// <summary>
|
||||
/// 记录一次行为执行,然后继续执行下一个处理器。
|
||||
/// 获取当前测试进程中该请求类型对应的行为触发次数。
|
||||
/// 该计数器是按泛型闭包共享的静态状态,测试需要在每次运行前显式重置。
|
||||
/// </summary>
|
||||
public static int InvocationCount
|
||||
{
|
||||
get => Volatile.Read(ref _invocationCount);
|
||||
set => Volatile.Write(ref _invocationCount, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以线程安全方式记录一次行为执行,然后继续执行下一个处理器。
|
||||
/// </summary>
|
||||
/// <param name="message">当前请求消息。</param>
|
||||
/// <param name="next">下一个处理委托。</param>
|
||||
@ -27,7 +35,7 @@ public sealed class TrackingPipelineBehavior<TRequest, TResponse> : IPipelineBeh
|
||||
MessageHandlerDelegate<TRequest, TResponse> next,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
InvocationCount++;
|
||||
Interlocked.Increment(ref _invocationCount);
|
||||
return await next(message, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,8 @@ internal class ComplexQuery : IQuery<ComplexResult>
|
||||
/// <returns>此前通过 <see cref="SetContext" /> 绑定的上下文实例。</returns>
|
||||
public IArchitectureContext GetContext()
|
||||
{
|
||||
return _context!;
|
||||
return _context ?? throw new InvalidOperationException(
|
||||
$"{nameof(SetContext)} must be called before {nameof(GetContext)}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -5,7 +5,7 @@ namespace GFramework.Core.Tests.Coroutine;
|
||||
/// <summary>
|
||||
/// 为协程测试提供固定时间步长的时间源。
|
||||
/// </summary>
|
||||
public class TestTimeSource : ITimeSource
|
||||
public sealed class TestTimeSource : ITimeSource
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前累计时间。
|
||||
|
||||
@ -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<string>("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<List<int>>("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<string>("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<List<int>>("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<string>("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<string>("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<string>("testKey");
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ namespace GFramework.Core.Tests.Environment;
|
||||
/// <summary>
|
||||
/// 为环境相关测试提供可写注册入口的测试环境实现。
|
||||
/// </summary>
|
||||
public class TestEnvironment : EnvironmentBase
|
||||
public sealed class TestEnvironment : EnvironmentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取测试环境名称。
|
||||
@ -13,11 +13,11 @@ public class TestEnvironment : EnvironmentBase
|
||||
public override string Name { get; } = "TestEnvironment";
|
||||
|
||||
/// <summary>
|
||||
/// 将测试数据注册到基础环境存储中,便于测试通过公开入口准备上下文。
|
||||
/// 将测试数据注册到基础环境存储中,便于测试通过显式测试辅助入口准备上下文。
|
||||
/// </summary>
|
||||
/// <param name="key">要注册的环境键。</param>
|
||||
/// <param name="value">要注册的环境值。</param>
|
||||
public new void Register(string key, object value)
|
||||
public void RegisterForTest(string key, object value)
|
||||
{
|
||||
base.Register(key, value);
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -25,7 +25,7 @@ public sealed class TestAsyncComplexQuery : AbstractAsyncQuery<TestAsyncQueryInp
|
||||
var result = new TestAsyncQueryResult
|
||||
{
|
||||
Value = input.Value * 2,
|
||||
DoubleValue = input.Value * 3
|
||||
TripleValue = input.Value * 3
|
||||
};
|
||||
|
||||
return Task.FromResult(result);
|
||||
|
||||
@ -31,7 +31,7 @@ public sealed class TestAsyncComplexQueryV4 : AbstractAsyncQuery<TestAsyncQueryI
|
||||
var result = new TestAsyncQueryResultV2
|
||||
{
|
||||
Value = input.Value * 2,
|
||||
DoubleValue = input.Value * 3
|
||||
TripleValue = input.Value * 3
|
||||
};
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ namespace GFramework.Core.Tests.Query;
|
||||
public sealed class TestAsyncQueryInput : IQueryInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置查询值。
|
||||
/// 获取查询值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
}
|
||||
|
||||
@ -6,12 +6,12 @@ namespace GFramework.Core.Tests.Query;
|
||||
public sealed class TestAsyncQueryResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置主结果值。
|
||||
/// 获取主结果值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置派生的双重结果值。
|
||||
/// 获取派生的三倍结果值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int DoubleValue { get; init; }
|
||||
public int TripleValue { get; init; }
|
||||
}
|
||||
|
||||
@ -6,12 +6,12 @@ namespace GFramework.Core.Tests.Query;
|
||||
public sealed class TestAsyncQueryResultV2
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置值
|
||||
/// 获取值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int Value { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置双倍值
|
||||
/// 获取三倍值;该值只能在对象初始化阶段设置。
|
||||
/// </summary>
|
||||
public int DoubleValue { get; init; }
|
||||
public int TripleValue { get; init; }
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -10,7 +10,7 @@ public sealed class TestAsyncState : IState, IAsyncState
|
||||
/// <summary>
|
||||
/// 获取或设置是否允许向目标状态转移。
|
||||
/// </summary>
|
||||
public bool AllowTransition { get; set; } = true;
|
||||
public bool AllowTransitions { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获取异步进入状态是否已被调用。
|
||||
@ -80,7 +80,7 @@ public sealed class TestAsyncState : IState, IAsyncState
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
CanTransitionToCallCount++;
|
||||
return AllowTransition;
|
||||
return AllowTransitions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -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
|
||||
/// 获取状态机当前维护的状态实例映射,供测试断言注册结果使用。
|
||||
/// </summary>
|
||||
/// <returns>状态类型到状态实例的只读视图。</returns>
|
||||
public IDictionary<Type, IState> GetStates()
|
||||
public IReadOnlyDictionary<Type, IState> GetStates()
|
||||
{
|
||||
return States;
|
||||
return States as IReadOnlyDictionary<Type, IState> ?? new ReadOnlyDictionary<Type, IState>(States);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ public class TestStateV5_2 : IState
|
||||
/// <returns>始终返回 <see langword="true" /> 以简化状态机切换测试。</returns>
|
||||
public bool CanTransitionTo(IState next)
|
||||
{
|
||||
_ = next;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -28,6 +29,7 @@ public class TestStateV5_2 : IState
|
||||
/// <param name="previous">前一个状态。</param>
|
||||
public void OnEnter(IState? previous)
|
||||
{
|
||||
_ = previous;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -36,5 +38,6 @@ public class TestStateV5_2 : IState
|
||||
/// <param name="next">下一个状态。</param>
|
||||
public void OnExit(IState? next)
|
||||
{
|
||||
_ = next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ public class AbstractContextUtilityTests
|
||||
Assert.That(utility.Destroyed, Is.True);
|
||||
|
||||
// 重置状态
|
||||
utility.Destroyed = false;
|
||||
utility.ResetDestroyedStateForTest();
|
||||
|
||||
// 第二次初始化和销毁
|
||||
utility.Initialize();
|
||||
|
||||
@ -14,12 +14,13 @@ public sealed class TestContextUtilityV1 : AbstractContextUtility
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置一个值,该值指示当前工具是否已执行销毁逻辑。
|
||||
/// 获取一个值,该值指示当前工具是否已执行销毁逻辑。
|
||||
/// </summary>
|
||||
public bool Destroyed { get; set; }
|
||||
public bool Destroyed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示测试初始化钩子是否已被调用。
|
||||
/// 获取一个值,该值指示测试专用的 <see cref="OnInit" /> 钩子是否已被调用。
|
||||
/// 该标记与 <see cref="Initialized" /> 共享同一执行时机,但单独暴露以便断言钩子本身已运行。
|
||||
/// </summary>
|
||||
public bool InitCalled { get; private set; }
|
||||
|
||||
@ -48,4 +49,12 @@ public sealed class TestContextUtilityV1 : AbstractContextUtility
|
||||
{
|
||||
Destroyed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置销毁标记,供同一实例的重复生命周期测试在下一轮初始化前清理观测状态。
|
||||
/// </summary>
|
||||
public void ResetDestroyedStateForTest()
|
||||
{
|
||||
Destroyed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,9 +13,9 @@ public sealed class TestContextUtilityV2 : AbstractContextUtility
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置一个值,该值指示当前工具是否已执行销毁逻辑。
|
||||
/// 获取一个值,该值指示当前工具是否已执行销毁逻辑。
|
||||
/// </summary>
|
||||
public bool Destroyed { get; set; }
|
||||
public bool Destroyed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个值,该值指示自定义初始化步骤是否已完成。
|
||||
|
||||
@ -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"`
|
||||
|
||||
@ -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`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user