![ET 框架通用测试用例包(cn.etetet.test):从 [Test] 自动发现到 Console 批量执行的完整测试体系](http://pic.xiahunao.cn/yaotu/ET 框架通用测试用例包(cn.etetet.test):从 [Test] 自动发现到 Console 批量执行的完整测试体系)
ET 框架通用测试用例包cn.etetet.test从 [Test] 自动发现到 Console 批量执行的完整测试体系【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET导读Packages/cn.etetet.test是 ET 框架内置的通用测试用例包它基于ConsoleMode.Test控制台模式运行通过[Test]特性自动发现用例并分发到对应处理器执行同时支持按包名与用例名的正则过滤批量执行。本文将从包的整体架构出发完整讲解测试的启动方式、命令参数、测试用例命名规范编译期强制校验、新用例编写范式、执行结果判定与常见失败排查并结合仓库源码TestConsoleHandler.cs、TestDispatcher.cs、TestFiberScope.cs 等深入底层分发与隔离机制帮助你在 ET 项目中快速落地可运行、可回归的自动化测试。一、包定位与整体架构1.1 包的核心职责根据包的 AGENTS.md 与 README.md该包解决三个核心问题自动发现基于[Test]特性见 TestAttribute.cs自动收集所有测试处理器无需手工注册统一执行入口以ConsoleMode.Test作为运行场景通过控制台命令统一驱动批量与过滤支持按包名与用例名的正则过滤适合快速验证模块逻辑与环境初始化流程。1.2 包内目录结构Packages/cn.etetet.test/ ├── Proto/ # 测试协议Test_C_10500.proto ├── Scripts/ │ ├── Model/Test/ # 测试框架模型层ATestHandler、TestDispatcher、TestArgs 等 │ ├── Hotfix/Test/ # 测试执行层TestConsoleHandler、FiberInit_TestCase、具体用例 │ └── Core/Share/ # ITestMessage 等共享定义 └── skills/ ├── et-tdd/ # 测试驱动开发流程 ├── et-test-write/ # 测试编写规范 └── et-test-run/ # 测试执行与排查从源码结构看Scripts/Model/Test/放置测试框架的基础类型接口、基类、参数、调度器、作用域Scripts/Hotfix/Test/放置控制台入口、场景初始化与实际用例skills/则面向 Agent 提供三类路由et-tdd完整 TDD 闭环、et-test-write编写用例、et-test-run执行与排查。AGENTS.md 明确要求这些 skill 采用“轻量路由 按需补读”模式命中测试任务时只读取对应的SKILL.md避免一次性加载全部测试规则。二、快速运行启动测试场景与交互式命令2.1 启动测试场景测试运行在独立的Test场景下通过控制台参数指定场景名启动pwsh -Command dotnet ./Bin/ET.App.dll --Console1 --SceneNameTest--Console1开启控制台模式--SceneNameTest指定进入Test测试场景。启动后即可在控制台交互式输入测试命令。2.2 交互式执行示例Test # 执行全部测试用例 Test --NameCreateRobot # 按正则过滤只执行类名匹配 CreateRobot 的用例 Test --NameCreateRobot2 # 无匹配时提示 not found test注意测试执行完成会退出进程。这一行为由 TestConsoleHandler.cs 中的Environment.Exit(exitCode)实现——测试结束后以 0/1 作为进程退出码退出便于脚本化集成与 CI 判断。2.3 命令参数详解Test命令的参数由 TestArgs.cs 使用 CommandLine 库定义参数短选项默认值说明--Name-n.*处理器类名正则匹配所有测试用例可用Test --NameCreateRobot收敛范围--Parallel-pfalse是否并行执行测试--MaxConcurrency无0最大并发数0表示使用框架默认并发策略其中--Name的解析与分发链路为控制台命令由TestConsoleHandler解析按正则从TestDispatcher获取匹配的处理器并逐一运行。2.4 示例输出 Test Test.Test_CreateRobot start Test.Test_CreateRobot success Test --NameCreateRobot Test.Test_CreateRobot start Test.Test_CreateRobot success Test --NameCreateRobot2 not found test! name: CreateRobot2三、核心类与底层分发机制AGENTS.md 给出了包内核心类清单下表为完整说明路径均为仓库内实际位置文件说明TestConsoleHandler.cs控制台处理器[ConsoleHandler(ConsoleMode.Test)]解析命令并进入测试模式TestDispatcher.cs按包名与处理器名正则筛选匹配的测试用例ATestHandler.cs测试基类约定Handle(...)接口FiberInit_TestCase.csTestCase场景初始化每个用例均为全新服务器环境TestArgs.cs命令行参数定义ITestHandler.cs测试处理器接口3.1 自动发现TestDispatcher 的装配过程TestDispatcher继承SingletonTestDispatcher并在Awake()中完成注册通过CodeTypes.Instance.GetTypes(typeof(TestAttribute))收集所有带[Test]特性的类型对每个类型用Activator.CreateInstance实例化并校验其实现了ITestHandler否则抛出异常以类型名为 key 存入SortedDictionarystring, ITestHandler保证按名称有序分发。Get(string name)使用System.Text.RegularExpressions.Regex对处理器类名做正则匹配同时读取可选的[TestExecutionAttribute]来决定执行模式默认TestExecutionMode.Parallel见 TestExecutionMode.cs最终返回TestCaseInfo列表。3.2 执行入口TestConsoleHandler 的完整流程TestConsoleHandler.cs 标注了[ConsoleHandler(ConsoleMode.Test)]其Run方法执行如下流程用Parser.Default.ParseArgumentsTestArgs(...)解析Test命令参数解析失败抛出异常调用TestDispatcher.Instance.Get(options.Name)获取匹配用例若为空则输出not found test!并Environment.Exit(1)记录开始时间调用TestRunHelper.Run(fiber, options, testCases)执行全部用例见 TestRunHelper.cs汇总TestCaseResult统计Total / Passed / Failed / Time(ms)失败时逐条列出失败用例名以failedTests.Count 0 ? 0 : 1作为进程退出码退出。3.3 用例隔离FiberInit_TestCase 与全新服务器环境FiberInit_TestCase.cs 标注[Invoke(SceneType.TestCase)]负责TestCase场景初始化其关键点在于忽略心跳消息日志ServiceHeartbeatRequest/Response避免噪音为根 Scene 添加TimerComponent、CoroutineLockComponent读取StartProcessConfig设置内网/外网地址注册AddressSingleton、ProcessFiberAddressSingleton、ServiceDiscoveryBootstrapSingleton创建ServiceDiscovery与ServiceDiscoveryAgentFiber本地测试的地址转发代理按StartSceneConfigCategory配置为进程内每个场景创建对应 Fiber。每个测试用例都是全新的服务器环境用例通过 TestFiberScope.cs 的Create方法分配独立 zone 并创建子 Fiber测试结束后由DisposeAsync通过fiber.RemoveFiber(...)回收配合FiberDestroyEvent_TestFiberDatabaseCleanup事件清理测试数据库残留从而保证用例之间互不污染、可重复执行。四、测试用例命名规范编译期强制继承ATestHandler的测试用例类必须遵守以下命名规范由分析器TestCaseNamingAnalyzerET0036在编译时强制检查违反将直接编译报错。4.1 命名规则命名格式{PackageType}_{TestName}_TestPackageType必须与所在包的PackageType常量匹配如Test、Robot、Map等TestName测试用例的描述性名称可包含多个下划线分隔必须以_Test结尾。文件位置必须放在包的Scripts/Hotfix/Test/目录下。PackageType 匹配规则cn.etetet.test→Testcn.etetet.robot→Robotcn.etetet.map→MapYIUI 相关包如cn.etetet.yiuiframework→YIUIFramework其他包首字母大写的包名最后部分4.2 正误示例// ✅ 正确在 cn.etetet.test 包中 public class Test_CreateRobot_Test : ATestHandler { } public class Test_Login_Success_Test : ATestHandler { } public class Test_Data_Validation_Test : ATestHandler { } // ❌ 错误缺少 _Test 后缀 public class Test_CreateRobot : ATestHandler { } // ❌ 错误PackageType 不匹配在 test 包中使用了 Robot 前缀 public class Robot_CreateRobot_Test : ATestHandler { } // ❌ 错误文件不在 Scripts/Hotfix/Test/ 目录4.3 编译错误示例违反命名规范时编译器会报错Test case class InvalidTest must follow naming pattern {PackageType}_{TestName}_Test and be placed in Scripts/Hotfix/Test directory: Class name must end with _TestTest case class Robot_Example_Test must follow naming pattern {PackageType}_{TestName}_Test and be placed in Scripts/Hotfix/Test directory: PackageType should be Test for package cn.etetet.test, but got Robot五、编写新测试用例5.1 编写步骤新建类继承ATestHandler注意父类已有[Test]特性子类无需重复添加严格遵守命名规范类名格式为Test_{描述}_Test文件必须放在Scripts/Hotfix/Test/目录下实现public override ETTaskint Handle(TestContext context)并用TestFiberScope创建TestCase纤程成功返回ErrorCode.ERR_Success即0失败返回非零错误码或抛出异常。5.2 完整代码示例using ET.Test; using ET.Server; namespace ET.Test { public class Test_MyCase_Test : ATestHandler { public override async ETTaskint Handle(TestContext context) { await using TestFiberScope scope await TestFiberScope.Create(context.Fiber, nameof(Test_MyCase_Test)); Fiber testFiber scope.TestFiber; await ETTask.CompletedTask; return ErrorCode.ERR_Success; } } }注意TestFiberScope.Create的完整签名见 TestFiberScope.cs为Create(Fiber fiber, int sceneType, string testName)仓库现有用例一般传入SceneType.TestCase或SceneType.TestEmpty使用await using保证作用域结束自动销毁测试 Fiber。参考仓库已有用例如 Test_CreateRobot_Test.cs、Test_ConfigLoader_CodeConfigReload_Test.cs、Test_RouterManagerAddressIsolation_Test.cs可看到TestCase/TestEmpty两种场景的实际用法。5.3 测试编写规范et-test-write按 skills/et-test-write/SKILL.md 的约定落点功能包自己的测试优先放在被测包内Packages/cn.etetet.{被测包}/Scripts/Hotfix/Test/跨包集成测试必须放到拥有该集成场景的业务包cn.etetet.test只承载测试框架本身与 test 包自身代码的测试。模型放置测试专用数据结构、Entity、Component、BT 节点或辅助模型必须放在被测包Scripts/Model/Test/不要放入Scripts/Model/Share/或Scripts/Hotfix/Test/。确定性测试必须是协程式、逻辑确定的验证按真实时序await消费事件、消息返回或明确完成信号禁止用固定时间等待、sleep、轮询、WaitMatch或无序过滤等待状态。Entity 安全含await的测试必须在await后通过EntityRef重新获取 Entity避免悬垂引用。配置隔离测试需要的 Config 数据必须由测试自己用代码构造不得修改已有 Excel、配置文件或导出的配置代码。错误码成功返回ErrorCode.ERR_Success失败直接返回唯一数字错误码不污染正式ErrorCode.cs测试失败用Log.Console普通信息用Log.Debug日志统一英文。六、返回值与日志判定成功返回0如ErrorCode.ERR_Success控制台输出success。失败返回非零或抛出异常控制台输出fail与错误信息。执行完成后控制台会输出汇总由TestConsoleHandler打印-------------------------------------------------------------------- Test Summary: Total: 3, Passed: 3, Failed: 0, Time: 234ms七、执行与失败排查et-test-run按 skills/et-test-run/SKILL.md 的默认动作先用dotnet build ET.sln编译除非用户明确只要看日志或已经完成编译运行测试前清理Logs/避免旧日志干扰服务端 / Hotfix 测试使用控制台Test命令Unity Editor 测试使用 UnityBridge 的UnityTestRunRequest按Name正则匹配执行失败时先看控制台首个失败点服务端测试再看Logs/All.logEditor 测试看 response 里的Message与Results[].Message服务端测试成功后也检查Logs/All.log确认没有隐藏异常或错误日志调试遵循先定位原因、再改代码不要为了跑通测试随意修改正常业务逻辑。常用命令# 编译 dotnet build ET.sln # 清理日志 Remove-Item ./Logs -Recurse -Force -ErrorAction SilentlyContinue # 运行全部服务端测试管道输入 Test 命令 Test | dotnet ./Bin/ET.App.dll --SceneNameTest # 运行指定用例 Test --NameCreateRobot | dotnet ./Bin/ET.App.dll --SceneNameTest # UnityBridge 探活 dotnet ./Bin/ET.UnityBridge.dll {_t:Ping} # 通过 UnityBridge 在 Unity Editor 中运行全部测试 dotnet ./Bin/ET.UnityBridge.dll {_t:UnityTestRunRequest,Name:.*} # 查看测试日志尾部 Get-Content ./Logs/All.log -Tail 200常见失败原因速查现象优先检查Entity 已失效await后是否通过EntityRef重新获取数据不一致测试准备与配置链路消息超时网络消息发送、事件是否真的发布Fiber 未找到场景或 Fiber 名称未找到测试类名、PackageType前缀、测试目录Editor 测试未匹配Name正则、类是否继承ET.Test.ATestHandler、是否在Scripts/Editor/Test/找不到UnityTestRunRequestUnity Editor 是否打开、UnityBridge 是否在线、是否执行过Refresh配置不存在测试是否自己用代码构造最小 Config 数据常见问题not found test无匹配用例。检查类名与正则是否匹配是否继承了ATestHandler热更/编译是否完成。正则匹配范围过大或过小调整--Name参数建议先用默认值.*确认整体列表再逐步收敛过滤范围。八、TDD 工作流et-tdd按 skills/et-tdd/SKILL.md 的约定使用测试驱动方式开发新功能或修复 Bug 时遵循完整闭环需求 - 测试方案 - 测试用例 - 实现 - 编译 - 运行 - 回归默认动作先理解需求读取相关包AGENTS.md查看现有实现与现有测试写代码前先补Test.md或最小验证清单明确测什么、怎么验、预期结果先写最小可跑测试用例再实现代码让测试通过编写测试叠加et-test-write实现业务叠加et-code涉及异步叠加et-async编译统一走dotnet build ET.sln运行目标测试再做必要回归成功后检查Logs/All.log完成后更新相关包内AGENTS.md沉淀实现原理、使用方式、测试入口或新增规则。三个 skill 的职责边界清晰只是执行已有测试用et-test-run只是补写测试用例用et-test-write只是编译或导出则走et-build避免重复加载规则。结语cn.etetet.test是 ET 框架中一个轻量而完整的测试基座[Test]特性驱动的自动发现 TestDispatcher正则分发 TestFiberScope按用例隔离的全新服务器环境配合TestCaseNamingAnalyzerET0036在编译期强制命名规范共同构成了从“写用例”到“批量回归”的闭环。结合 skills/ 下的三个 SKILL 文档与仓库内已有测试用例Test_CreateRobot_Test.cs、Test_ParallelRunner_Metadata_Test.cs 等你可以快速为自己的功能包建立“确定性、可隔离、可过滤、可回归”的自动化测试体系。【免费下载链接】ETUnity3D Client And C# Server Framework项目地址: https://gitcode.com/GitHub_Trending/et/ET创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考