ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Haxe 单元测试体系实战指南:tests/unit 回归测试编写与多目标运行

Haxe 单元测试体系实战指南:tests/unit 回归测试编写与多目标运行 编程语言编译器语言运行时标准库【免费下载链接】haxeHaxe - The Cross-Platform Toolkit项目地址https://gitcode.com/gh_mirrors/ha/haxe点击查看免费下载导读Haxe 编译器仓库自带一套覆盖全部官方目标的单元测试套件集中在 tests/unit 目录。本文以该目录下的 tests/unit/README.md 为骨架系统讲解每个 Bug 修复一个回归测试文件的约定、测试文件的组织与自动发现机制以及如何在 Lua、JS、HL、Neko、PHP、CPP、JVM、Python 等目标上编译并运行整套测试。读完本文你将掌握在 Haxe 仓库中为 bug 修复添加回归测试的标准流程、测试基类提供的断言辅助方法以及基于 utest 的跨目标测试基础设施的工作原理。一、测试套件全景tests/unit 目录结构与定位tests/unit是整个 Haxe 官方仓库中规模最大的测试工程源码体量达数千个.hx文件。其顶层结构如下以仓库根目录为起点路径作用tests/unit/compile-each.hxml所有目标共享的公共编译配置类路径、资源、宏、DCE 等tests/unit/compile-*.hxml面向各目标的入口配置Lua、JS、HL、Neko、PHP、CPP、JVM、Python、Macro 等tests/unit/compile.hxml通过--next依次编译全部目标的一键配置tests/unit/src/unit/Test.hx测试基类提供全部断言辅助方法tests/unit/src/unit/TestMain.hx测试入口实例化并注册所有测试类驱动 utest Runnertests/unit/src/unit/TestIssues.hx用编译期宏自动扫描目录、批量注册测试类tests/unit/src/unit/issues/按 issue 编号组织的回归测试当前仓库快照中有 1200 个文件tests/unit/src/unit/hxcpp_issues/hxcpp 目标相关的专项 issue 测试tests/unit/src/unit/teststd/标准库 API 的功能测试如 Array、String 等tests/unit/debug_utest/为开发新目标而准备的极简测试框架替代品bin/编译产物输出目录运行测试时由各 hxml 写入需要特别说明目录中的compile.hxml是一个总入口它用 Haxe 多目标配置语法--next串起全部目标从 Flash、JS、HL 到 CPP、JVM、Python、Macro 逐个编译而单个目标通常只编译对应目标二者结合便可以在 CI 中实现一次提交全平台回归。二、测试文件位置的约定原文档用一张表明确划分了三类测试的存放位置这也是新增测试时首先需要遵守的约定位置用途src/unit/issues/IssueXXXXX.hx每个 issuebug一条回归测试一一对应src/unit/Test*.hx通用功能/目标相关测试src/unit/spec/规范specification测试换算为仓库根目录相对路径即是tests/unit/src/unit/issues/IssueXXXXX.hx回归测试文件名与 issue 编号一一对应tests/unit/src/unit/Test*.hx功能级测试例如 tests/unit/src/unit/teststd/TestArray.hx 专门验证标准库Array的length、concat、join、pop等行为src/unit/spec/原文档约定用于规范类测试的目录。在本文所基于的仓库快照中该目录下暂未见实际文件新增规范测试时应遵循文档中的目录约定并参照现有测试的包名、命名风格落位。从源码结构看Test*.hx与Issue*.hx两类文件都无需手工登记到任何清单中——注册工作由入口与宏自动完成详见第四节这正是新增文件即自动参与测试这一约定的实现基础。三、为 Bug 修复添加回归测试原文档强调的核心理念是修 bug 必须同时提交回归测试且每个 issue 一个文件。这一模式带来三个直接收益避免合并冲突——不同开发者修复不同 issue 时写各自的IssueXXXXX.hx互不覆盖对应关系一目了然——从文件名即可知道该测试守护的是哪个 issue自动随套件运行——测试文件只要放进src/unit/issues/就会被自动发现、自动编译进各目标。3.1 标准模板原文档给出的模板如下可直接作为新文件的基础package unit.issues; class Issue12345 extends Test { // Use #if for target-specific tests #if lua function test() { // Test that would fail without the fix eq(actualValue, expectedValue); } #end }对该模板有两点实战提示类名Issue12345中的编号应替换为真实 issue 编号保持Issue前缀大写模板中写extends Test实际仓库里大量测试写作extends unit.Test例如 tests/unit/src/unit/issues/Issue10007.hx因为基类定义在unit包内见 tests/unit/src/unit/Test.hx。为避免歧义建议统一使用带包名的extends unit.Test写法。3.2 条件编译控制目标范围模板中的#if lua ... #end是 Haxe 条件编译用于限定测试只在特定目标上生效。这是回归测试的关键手法当某 bug 只在特定目标如lua、hl、jvm、cpp、python、php、js上出现时用#if 目标名包裹测试体避免在其他目标上误报失败也可以反向使用#if !php #end排除不支持该特性的目标。例如 tests/unit/src/unit/TestMain.hx 中便用#if (!php !lua)跳过 HTTP 测试。3.3 测试基类提供的断言辅助方法新增测试不直接调用 utest 的Assert.*而是继承 tests/unit/src/unit/Test.hx 获得一组封装好的断言方法均在 Test.hx 中定义。常用方法如下方法语义底层实现eq(v, v2)判断两个值相等utest.Assert.equalsfeq(v, v2)浮点数近似相等utest.Assert.floatEqualsaeq(expected, actual)数组内容整体相同utest.Assert.samet(v)/f(v)断言为真 / 为假utest.Assert.isTrue/isFalseassert(?message)无条件失败用于标记不应到达的分支utest.Assert.failexc(f)断言函数执行抛出异常utest.Assert.raisesunspec(f)捕获任意异常并继续不产生断言失败try/catch noAssert()allow(v, values)断言 v 属于给定集合utest.Assert.containsnoAssert()空断言占位内部置为通过恒真断言hf / nhf / hsf / nhsf断言类具有/不具有某实例字段或静态字段基于Type.getInstanceFields/Type.getClassFields与Lambda.has由于这些辅助方法带有?pos:haxe.PosInfos位置信息参数断言失败时能精准报告到测试源码行号便于快速定位。3.4 真实仓库案例看两个取自仓库的实例体会实际写法案例一tests/unit/src/unit/issues/Issue10007.hx 验证抽象类型通过:forward.new转发的构造行为package unit.issues; class Issue10007 extends unit.Test { function test() { final ctor Abstract.new; var o ctor(); t(o.isImpl()); } } :forward.new private abstract Abstract(Impl) { public function isImpl():Bool return Std.isOfType(this, Impl); } private class Impl { public function new() {} }案例二tests/unit/src/unit/hxcpp_issues/Issue173.hx 验证 hxcpp 目标上接口与私有类的转换package unit.hxcpp_issues; private class X1 implements Y1 { public function new () {} } private interface Y1 extends Z1 {} private interface Z1 {} class Issue173 extends Test { function test() { var z:Z1 new X1(); t(z ! null); } }注意 hxcpp 专项测试位于独立的hxcpp_issues包中与通用 issue 回归测试分开存放。四、自动发现与注册机制源码级剖析新增的测试文件为什么自动运行答案在入口与宏里。4.1 入口与 Runnertests/unit/src/unit/TestMain.hx 是所有compile-*.hxml声明的--main类。其main()流程为JS 目标时将trace输出重定向到页面haxe:trace元素TestMain.hx便于浏览器内调试硬编码实例化一批功能测试类TestOps、TestBasetypes、TestBytes、TestEReg、TestGADT、TestCoroutines等并大量使用#if按目标裁剪见 TestMain.hx调用TestIssues.addTestClasses与addIssueClasses扫描目录、批量追加测试类TestMain.hx用utest.Runner注册全部测试类utest.ui.Report输出报告并通过runner.onProgress汇总断言结果决定successTestMain.hx。4.2 目录扫描宏tests/unit/src/unit/TestIssues.hx 提供两个编译期宏addIssueClasses(dir, pack)读取src/unit/issues及hxcpp_issues目录下所有以.hx结尾的文件把去掉扩展名的类名逐个构造成classes.push(new $tp())的宏表达式TestIssues.hx。这也解释了.disabled后缀的作用Issue193.hx.disabled不以.hx结尾扫描时被天然跳过成为软禁用的测试文件addTestClasses(dir, pack)递归遍历目录收集以Test开头且.hx结尾的类TestIssues.hx覆盖unit.teststd等标准库测试包。由于该机制存在新增Issue*.hx或Test*.hx文件后无需改动任何登记清单下一次编译便自动纳入套件。五、编译与运行多目标测试实操5.1 单目标编译运行以 Lua 为例原文档给出的核心命令# 编译 Lua 目标 haxe --cwd tests/unit compile-lua.hxml # 运行 lua bin/unit.lua拆解--cwd tests/unit的含义它把工作目录切换到测试工程使compile-lua.hxml中相对路径如-p src、--resource res1.txt、bin/unit.lua都相对tests/unit生效。前提是本机已安装对应目标的运行时编译阶段需要可用的haxe编译器以及 utest 库-lib utest可通过haxelib install utest安装运行阶段需要目标运行时例如 Lua 需要lua解释器、Neko 需要neko虚拟机、HL 需要hl解释器、JVM 需要java等。5.2 各目标入口一览tests/unit下按目标提供了成对的编译配置均在compile-*.hxml中先include公共配置再追加目标专属参数目标hxml 入口运行方式产物在bin/Luatests/unit/compile-lua.hxmllua bin/unit.luaJStests/unit/compile-js.hxml浏览器打开bin/unit.js配合TestMain的 trace 重定向Macro/解释执行tests/unit/compile-macro.hxml使用--interp直接解释执行HLtests/unit/compile-hl.hxmlhl bin/unit.hlHLCtests/unit/compile-hlc.hxml先编译为 C 再链接运行Nekotests/unit/compile-neko.hxmlneko bin/unit.nPHPtests/unit/compile-php.hxmlphp bin/...CPPtests/unit/compile-cpp.hxml编译后执行生成的二进制JVMtests/unit/compile-jvm.hxmljava -jar bin/unit.jar内部由compile-java-native.hxml与compile-jvm-only.hxml两个阶段组成Pythontests/unit/compile-python.hxmlpython bin/unit.py全部目标tests/unit/compile.hxml用--next依次编译 Flash/JS/HL/HLC/Lua/Neko/PHP/CPP/JVM/Python/Macro以 tests/unit/compile-lua.hxml 为例其完整内容仅两行compile-each.hxml --main unit.TestMain -lua bin/unit.lua即公共配置 主入口 目标输出三件套。其他目标的 hxml 结构完全一致只替换第三行为-js bin/unit.js、--interp等对应参数。测试报告的成败判断由 TestMain.hx 中的runner.onProgress统一汇总在 cpp/neko/php 目标上还可通过-v参数开启逐测试的 verbose 输出TestMain.hx。5.3 公共编译配置解析tests/unit/compile-each.hxml 是全部目标共享的基础配置理解它对排查为什么这个测试没跑起来很有帮助-D source-header --debug -p src --resource res1.txtre/s?!%[]))(1.txt --resource res2.binre/s?!%[]))(1.bin --resource serializedValues.txt --macro Macro.init() --dce full -lib utest -D analyzer-optimize -D analyzer-user-var-fusion -D message.reportingpretty -D haxe-next逐项说明-p src源码路径指向tests/unit/src--resource将三个资源文件打包进编译产物供haxe.Resource测试使用资源名故意包含特殊字符以验证资源命名解析--macro Macro.init()在编译期执行测试工程自身的宏初始化--dce full全量 DCE死代码消除确保测试代码只保留被引用部分-lib utest引入 utest 测试框架断言、Runner、Report 均来自该库-D analyzer-optimize/-D analyzer-user-var-fusion开启编译器分析器的变量融合优化同时兼作优化器自身的测试场景-D message.reportingpretty美化编译错误信息输出-D haxe-next启用实验性语法/特性开关--debug保留调试信息便于对失败断言回溯。六、测试基础设施与调试辅助6.1 debug_utest面向新目标的极简测试框架debug_utest/README.md 说明debug_utest是 utest 的极简替代实现目标是让新目标的单元测试运行尽可能简单不必完整支持 utest 的处理流程。若要在新目标上启用它需要修改 tests/unit/compile-each.hxml移除-lib utest追加-cp debug_utest将tests/unit/debug_utest/加入类路径其中提供了utest.Assert、utest.ITest、utest.Runner等同名类型的最小实现位于tests/unit/debug_utest/utest/下追加-dce no部分测试可能因依赖 utest 特性而无法编译需要按.disabled方式临时禁用可选地启用utest.Macros.GENERIC把eq()变为泛型函数——有助于对原生代码做单元测试但同样会导致部分测试无法编译。6.2 测试资源的组织测试套件还依赖三类数据文件文本资源tests/unit/res1.txt、二进制资源tests/unit/res2.bin以及序列化样例tests/unit/serializedValues.txt它们经--resource嵌入编译产物供TestResource、TestSerialize等用例验证资源读取与序列化兼容性tests/unit/java_drivers/下的 JDBC 驱动 jar 则是 JVM 目标某些集成用例的运行时依赖。七、实战建议与工作流结合原文档约定与仓库现状为 Haxe 仓库贡献回归测试的推荐流程为确认 issue 编号例如12345命名文件tests/unit/src/unit/issues/Issue12345.hx包名unit.issues继承unit.Test编写function test()方法用eq/t/exc等辅助方法表达修复前会失败、修复后通过的断言判断目标范围仅在特定目标复现时用#if或#if !限定若是 hxcpp 专属问题放入tests/unit/src/unit/hxcpp_issues/本地验证先用最接近的目标验证如haxe --cwd tests/unit compile-lua.hxml lua bin/unit.lua再按需运行 tests/unit/compile.hxml 做全目标回归提交随 bug 修复一并提交测试文件无需修改任何注册清单——自动发现宏会将其纳入后续所有目标的 CI 回归。需要留意的前提与限制本套件依赖外部 utest 库与各目标运行时脱离仓库环境单独运行需先haxelib install utest部分测试如TestHttps在 php/lua 目标被刻意排除以规避 CI 不稳定新增测试若涉及网络或平台特有 API应沿用同样的条件编译与目录分层策略。赞分享编程语言编译器语言运行时标准库【免费下载链接】haxeHaxe - The Cross-Platform Toolkit项目地址https://gitcode.com/gh_mirrors/ha/haxe点击查看免费下载相关推荐一次搞懂抖音批量下载从主页归档到直播录制的完整避坑指南一次搞懂抖音批量下载从主页归档到直播录制的完整避坑指南 把别人主页的教程视频收藏进 App一个月后想批量留存时发现官方保存都带水印手动录屏则既费时又糊。d网页爬虫CLIOpenSCAD 测试体系实战指南回归测试、单元测试与 GUI 测试的运行与扩展OpenSCAD 测试体系实战指南回归测试、单元测试与 GUI 测试的运行与扩展 OpenSCADThe Programmers Solid 3D CAD教程人工智能机器学习深度学习Gatsby 集成测试体系实战指南Jest JSDOM 回归测试的编写与运行Gatsby 集成测试体系实战指南Jest JSDOM 回归测试的编写与运行 在 Gatsby 的 monorepo 中 integration tes前端静态站点Web框架上一篇Envoy AWS Request Signing 过滤器的凭证提供者链Credentials Provider Chain完全指南下一篇Vector 缓冲改进RFC 9477从 LevelDB 磁盘缓冲到可组合的缓冲拓扑创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表