首页/新闻资讯/正文详情

Erlang/OTP EUnit 版本演进全解:从 2.0 到 2.11 的核心特性、宏与源码实现

发布时间:2026/9/23 13:59:56 来源:云帆数科 栏目:资讯中心
Erlang/OTP EUnit 版本演进全解:从 2.0 到 2.11 的核心特性、宏与源码实现
Erlang/OTP EUnit 版本演进全解从 2.0 到 2.11 的核心特性、宏与源码实现【免费下载链接】otpErlang/OTP项目地址: https://gitcode.com/gh_mirrors/ot/otpEUnit 是 Erlang/OTP 官方的轻量级单元测试框架首次随 OTP 发布的版本即由 Richard Carlsson 贡献本文基于仓库内的官方发布说明 lib/eunit/doc/notes.md 完整梳理其从 2.0 到 2.11 的演进历程并结合 eunit.hrl、eunit.erl 等源码剖析randomDelay、scale_timeouts、capturedOutput、surefire 报告、peer 节点等关键机制的实际实现。读完本文你将能准确理解每个 EUnit 版本新增了什么、为什么这样设计以及如何在 OTP 当前版本中正确使用这些特性编写健壮的单元测试。EUnit 版本演进总览EUnit 于 2.0 版本正式进入 Erlang/OTP此后经历了十余个版本的迭代。当前仓库中 vsn.mk 标注的版本号为EUNIT_VSN 2.11。以下总览表概括了每个版本的核心变更依据 lib/eunit/doc/notes.md版本类型核心变更2.0新功能首个随 OTP 发布的 EUnit 版本作者 Richard Carlsson2.1新功能重构事件协议修复超时导致挂起的问题新增 surefire 报告后端面向 Maven/Bamboo2.1.5~2.1.7新功能/修复文档构建可开源化surefire 错误信息深度提升至 100修复 surefire 停止时的竞态2.2.1修复每个测试套件生成独立的 surefire XML新增assertNotMatch/assertNotEqual/assertNotException宏debugMsg打印当前进程 pidModule_tests.erl不再被执行两次2.2.2新功能OTP 支持并行 make如make -j62.2.3新功能新增no_tty选项静默默认终端报告测试表示{test,M,F}正式化{M,F}二元组被弃用识别 R15 新栈轨迹格式生成器返回异常值会被启发式检测并告警surefire 输出使用 UTF-8 编码2.2.4~2.2.13修复/新功能编码注释、宏包裹 begin...end、I/O 协议错误处理、appup 修正、Unicode 安全、debugVal/2截断深度控制2.3.1修复断言移入独立头文件后测试自动启用失效的问题2.3.3~2.3.8修复surefire 报告名去除内嵌双引号、Unicode 原子显示、get_until显式编码处理2.4~2.4.1新功能移除编译器警告surefire 剥离控制码避免生成非法 XML2.5新功能surefire 跳过非法 XML 1.0 字符新增?capturedOutput宏新增异常打印深度限制选项2.6~2.6.1新功能/修复修复编译器警告eunit_surefire报告处理器自动创建存储 XML 所需的目录2.7新功能测试用例超时时报告中包含 stacktrace2.8新功能可选项关闭对_tests后缀关联模块的自动执行避免源与测试同目录时的重复执行2.8.1修复exact_execution选项与 application 原语配合工作2.8.2新功能用tuple_size/1、byte_size/1替换size/1后者未被 JIT 优化且影响 Dialyzer 类型推断2.9新功能新增scale_timeouts选项可按比例缩放超时2.9.1新功能文档迁移至 Markdown 与 ExDoc2.10新功能实现 EEP-69 名义类型Nominal Types重构 opaque 处理许可证头统一为 SPDX 格式2.10.1新功能移除已弃用的 slave 模块用法fixture 的节点启动参数接受字符串或字符串列表2.10.2新功能release 目录结构梳理SBOM软件物料清单改进2.10.3修复修复{node,...}实例化传递节点名而非 pid恢复非分布式节点的net_kernel自动启动2.11新功能新增randomDelay宏支持-unsafe属性与不安全函数调用告警EUnit 2.11randomDelay宏与-unsafe支持作为当前最新版本EUnit 2.11 带来两项重要能力均可在仓库源码中找到对应实现。randomDelay注入随机延迟暴露时序竞态发布说明指出2.11 新增了randomDelay宏用于在测试执行中引入非确定性延迟帮助暴露**竞态条件race condition**与依赖精确时序才能显现的缺陷。在 eunit.hrl 中可以看到它的完整实现-ifdef(NODEBUG). -define(randomDelay(Prob, MinSec, MaxSec), ok). -else. -define(randomDelay(Prob, MinSec, MaxSec), (fun() - case rand:uniform() (Prob) of true - %% Convert seconds to milliseconds for timer:sleep Delay (MinSec) rand:uniform() * ((MaxSec) - (MinSec)), timer:sleep(round(Delay * 1000)); false - ok end end)()). -endif.其语义是以概率Prob触发延迟延迟时长在MinSec到MaxSec秒之间均匀随机取值源码内部先将秒转换为毫秒再调用timer:sleep/1。使用时形如?randomDelay(0.5, 0, 1)表示约 50% 的概率在 0~1 秒内随机休眠。注意两点宏被包裹在fun() - ... end立即调用中符合 EUnit 宏“不泄漏局部变量”的惯例见 eunit.hrl 顶部注释与调试类宏一致如果定义了NODEBUGrandomDelay会被替换为ok不产生任何运行时效果。该宏的官方文档说明位于 chapter.md 的“Macros for instrumentation”一节。-unsafe属性与不安全函数调用检测2.11 的另一项能力与编译器联动支持-unsafe属性用于把函数标记为“不安全使用”。它类似于弃用deprecation但又彼此独立且编译器默认会对调用 OTP 中已知始终不安全的函数生成警告。配套地xref新增了三类分析跨应用调用缺少-doc属性的函数undocumented_function_calls、调用标记为-doc false.的函数private_function_calls、以及调用不安全函数unsafe_function_calls。这为依赖审计与 API 治理提供了静态检查手段。超时、并行与测试控制选项的演进超时与并行执行是 EUnit 的核心控制能力多个版本持续打磨。scale_timeouts按比例缩放超时2.9EUnit 2.9 引入了scale_timeouts选项允许按数值因子整体缩放所有超时适合在较慢的宿主机上运行测试。在 eunit.erl 的test/2选项文档中明确说明{scale_timeouts,10}使超时放大 10 倍{scale_timeouts,0.1}则缩短为原来的 1/10。仓库自测套件 eunit_SUITE.erl 中即包含scale_timeouts_test/1对该行为的回归验证。timeout 原语的底层实现超时是测试表示中的一等公民{timeout, Time::number(), Tests}Time 单位为秒例如0.1表示 1/10 秒。在解析层eunit_data.erl 将其转换为内部时钟刻度parse({timeout, N, T}, Options) when is_number(N), N 0 - group(#group{tests T, options Options, timeout round(N * ?TICKS_PER_SECOND)});同时 eunit_data.erl 的push_timeout/3展示了关键语义当超时设置在带 fixturecontext的分组外层时超时时间包含 setup 与 cleanup 的执行时间且一旦超时触发整个 fixture 会被强制终止不执行 cleanup。单个测试的默认超时为 5 秒。EUnit 2.7 起测试超时时报告中会附带 stacktrace便于定位卡住的代码位置。并行执行与取消报告2.10EUnit 2.10 修复了一个并行测试场景的缺陷当多个测试并行运行、其中一个因 setup 失败被取消时该测试现在会被正确报告为 “cancelled”此前该取消会被静默忽略。回归测试report_failed_setup_inparallel_test/1记录在 eunit_SUITE.erl 中。并行控制原语包括{inparallel, Tests}尽可能并行与{inparallel, N, Tests}最多 N 个并发子测试。exact_execution精确控制测试范围2.8/2.8.1默认情况下eunit:test(m)不仅测试模块m还会自动寻找并执行m_tests模块中的测试。当源码与测试模块位于同一目录、执行顺序敏感时这种自动扩展可能造成重复执行。EUnit 2.8 增加了开关exact_execution布尔标志置true时不再自动执行_tests后缀模块2.8.1 又修复了该选项与{application, ...}原语配合时失效的问题。在 eunit.erl 的选项文档中对此有明确描述exact_execution的语义验证见 eunit_SUITE.erl 的eunit_exact_test/1。测试表示与断言宏的演进测试表示正式化{test,M,F}2.2.3EUnit 2.2.3 引入正式的三元组表示{test,M,F}指代M:F/0函数同时原有的二元组{M,F}被标记为弃用。从 chapter.md 的 “Simple test objects” 一节可以看到完整定义一个简单测试对象可以是零参 fun、{test, Module, Function}元组、带行号的{LineNumber, SimpleTest}对通常由?_test(...)宏产生。此外?前缀宏如?_assert(...)本质是?_test(?assert(...))的语法糖而_test(Expr)展开为{?LINE, fun () - (Expr) end}自动携带源码行号。断言宏家族扩充2.2.1EUnit 2.2.1 新增了assertNotMatch(Guard, Expr)、assertNotEqual(Unexpected, Expr)与assertNotException(Class, Term, Expr)补全了断言宏的正反两面这些宏在下划线前缀形式?_assertNotMatch等下均可用实现位于 eunit.hrl。注意 2.2.3 还改进了错误信息布局先打印 stacktrace 再打印错误项。?capturedOutput断言标准输出2.5EUnit 会捕获测试函数写入标准输出的内容2.5 新增的?capturedOutput宏允许在测试内部取回这些输出并进行断言。其实现见 eunit.hrl在?UNDER_EUNIT为真时调用eunit_proc:get_output()否则返回空字符串-define(capturedOutput, case ?UNDER_EUNIT of true - eunit_proc:get_output(); false - end).典型用法io:format(Hello~n), ?assertEqual(Hello\n, ?capturedOutput)debugVal/2与打印深度控制2.3/2.52.3 新增debugVal/2允许显式指定项的打印截断深度默认深度由EUNIT_DEBUG_VAL_DEPTH宏控制默认 15见 eunit.hrl?debugVal(Expr)会打印形如f(X) 42的源码与值对2.5 增加了限制测试套件异常打印深度的选项对应print_depth选项见 eunit.erl。性能相关的小改进2.8.2EUnit 2.8.2 将内部size/1调用替换为tuple_size/1或byte_size/1因为size/1不受 JIT 优化且可能使 Dialyzer 推导出更差的类型。这既是一次内部清理也提示了 Erlang 编程的通用最佳实践已知是元组用tuple_size/1已知是二进制用byte_size/1若可能为 bitstring需先用is_binary/1确认。surefire 报告后端面向 Maven/Bamboo 的持续打磨surefire 是 EUnit 的事件监听器后端用于生成 Maven 与 Atlassian Bamboo 可解析的 XML 测试报告入口见 eunit_surefire.erl。它经历了一条完整的打磨路线版本变更2.1新增 surefire 报告后端2.1.7报告内错误消息深度提升到 100终端输出才有深度限制XML 应包含更多信息修复停止时向 eunit 回传导致竞态的问题2.2.1每个测试套件生成独立 XML此前所有模块挤在一个报告里归属随机修正报告输出为 UTF-82.3.3报告名不再内嵌双引号2.4.1从 surefire 输出中剥离控制码避免生成非法 XML2.5跳过非法 XML 1.0 字符2.6.1自动创建存储 XML 所需的目录回归测试surefire_ensure_dir_test/1在 eunit_SUITE.erl 中使用示例见 eunit_surefire.erl 的模块文档eunit:test([fib, eunit_examples], [{report,{eunit_surefire,[{dir,.}]}}]).报告目录通过dir选项配置默认值为.源码中-define(XMLDIR, .)。节点与 fixture从 slave 到 peer 的演进{node,...}实例化修复2.10.3EUnit 2.10.3 修复了{node, ...}实例化时的一个缺陷现在正确地传递**节点名node name**而非 pid同时恢复了非分布式节点的net_kernel自动启动。这意味着基于 peer 节点的测试在普通非分布式节点上也能可靠工作。移除 slave参数化 Args2.10.1EUnit 2.10.1 移除了对已弃用slave模块的全部使用slave已被peer取代。同时fixture 中启动测试节点的Args参数现在既接受字符串也接受字符串列表传字符串时会被解析为参数列表单/双引号包裹的文本视为单个参数并去掉引号可用反斜杠转义保留引号详见 chapter.md 的 Fixtures 一节。fixture 的四种形态EUnit 的 fixture 表示在 chapter.md 中有系统定义核心类型为Setup() - R测试前执行并返回状态值Cleanup(R) - any()测试结束后执行无论成败、超时与否Instantiator(R) - Tests或{with, [AbstractTestFun]}把 setup 返回值实例化进测试Wherelocal|spawn|{spawn, Node}控制执行位置。四种组合形式分别为{setup, Setup, Tests}、{setup, Setup, Cleanup, Tests}、{setup, Where, Setup, Tests}与{setup, Where, Setup, Cleanup, Tests}foreach为每个测试集重复 setup/cleanupforeachx额外携带每项独立的X参数。Where默认是spawn当前进程负责 setup/teardown测试在子进程执行local模式下若测试超时导致进程被杀cleanup 不会执行因此对文件等持久化 fixture 应避免使用local。并行运行、事件协议与内部机制2.1/2.2.5/2.10EUnit 2.1 重构了事件协议修复了可能导致 EUnit 挂起的超时问题并让编写新的报告后端变得更加容易同时测试表示不再被遍历两次第一次仅用于枚举消除了对生成器写法的一些限制。从 eunit.erl 的listeners/1可以看到监听器机制eunit_tty始终运行负责发送最终{result,...}消息其余通过{report, {Mod, Opts}}选项挂载event_log选项则可把原始事件写入日志文件便于调试。其他值得一提的内部改进包括2.2.5 将 EUnit 宏包裹进begin ... end块避免宏展开带来的作用域问题2.10 移除了宏内对已弃用正则库的依赖并改用re2.2.10 使 EUnit 应用 Unicode 安全。构建、发布与合规基础设施的演进近年来 EUnit 的版本变更越来越聚焦于工程基础设施2.9.1文档迁移到 Markdown 与 ExDoc本仓库中的 lib/eunit/doc/guides/chapter.md 即为该迁移的产物2.10.2make release只把必要代码放入发布目录文档与示例不再混入make release_docs将文档放入发布树doc目录make release_tests将测试独立成目录。SBOM 方面为asmjit、zlib增加optional_components_of关系将make与erts下的 autoconf 脚本归类为build_tool_of所有configure/Makefile.in等文件纳入特定 SPDX 包。发布后可执行./Install -minimal \pwd并将 release 加入PATH 来验证2.10统一许可证头格式加入SPDX-License-Identifier如 eunit.hrl 头部的Apache-2.0 OR LGPL-2.1-or-later2.10作为 EEP-69 名义类型的附带影响重构了所有 opaque 类型处理逻辑并改进 Dialyzer 的 opaque 警告——opaque 类型检查的向后兼容性不保留旧警告措辞可能略有变化新增opaque_union警告及no_opaque_union关闭选项。从发布历史中提炼的 EUnit 使用要点综合 notes.md 各版本变更可以总结出以下对当前开发者仍然适用的实践准则测试命名..._test()是简单测试函数..._test_()是测试生成器m_tests模块会被自动纳入eunit:test(m)的执行范围若需精确控制可用exact_execution选项断言优先用专用宏assertMatch/assertEqual/assertException家族比裸模式匹配产生更详细的错误信息判断异常用assertError/assertExit/assertThrow捕获输出做断言用?capturedOutput验证标准输出内容时序敏感代码用randomDelay在并发路径上注入随机延迟以暴露竞态慢主机上缩放超时使用{scale_timeouts, N}而非逐个修改超时fixture 的Where慎用local超时被杀后 cleanup 不会执行持久化资源应依赖默认的spawn生成大量测试用惰性生成器每次调用返回单条测试加新生成器避免一次性占用过多内存模式见 chapter.md 的 Lazy generators 一节保证可移植编译若需在无 EUnit 环境下编译将-include_lib(eunit/include/eunit.hrl)与测试代码置于-ifdef(TEST)条件编译块内或默认定义NOTEST并在需要时用-DTEST覆盖。EUnit 的演进史既是一部测试框架功能完善史也折射出 Erlang/OTP 整体工程实践的变迁——从替代正则库、移除弃用模块到统一 SPDX 许可证头与 SBOM 合规。理解这些变更背后的源码实现宏展开逻辑、超时解析、监听器机制能帮助你在编写测试时更精准地选择 API并预判其行为边界。【免费下载链接】otpErlang/OTP项目地址: https://gitcode.com/gh_mirrors/ot/otp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

搞定刘海屏适配的3个性能优化坑,新手必看
搞定刘海屏适配的3个性能优化坑,新手必看

搞定刘海屏适配的3个性能优化坑,新手必看 刚学会写 CSS 和 JS 的人,最容易卡在“语法都懂,代码一跑就崩”的环节。特别是做移动端前端,一遇到刘海屏、挖孔屏,页面布局直接错位,这时候盲目堆砌 CSS 属性不仅难看,更会引发严重的… · 2026/9/23 13:59:56

TFTLCD原理详解:从像素电路到初始化时序与避坑指南
TFTLCD原理详解:从像素电路到初始化时序与避坑指南

简介:这份PDF资料围绕TFT LCD液晶显示器的驱动原理展开,面向显示技术初学者、硬件工程师及电子相关专业学生,帮助读者系统理解液晶面板从像素结构到整机驱动的完整逻辑。资源共1个PDF文件,压缩包约5.05MB,内容以图文结… · 2026/9/23 13:59:49

一维条形码识别原理与实战:从光信号到解码全解析
一维条形码识别原理与实战:从光信号到解码全解析

很多人第一次接触“一维条形码识别”,可能觉得这只是扫码枪“嘀”一声的事,没什么可深究的。但自己动手做过自动售货机、仓储系统或者哪怕只是想写一个识别工具的人,都会发现这“嘀”的一声背后,其实是光学、模拟电路、数字信号处… · 2026/9/23 13:59:49

3步搞定previouspage:从入门到精通避坑指南
3步搞定previouspage:从入门到精通避坑指南

3步搞定previouspage:从入门到精通避坑指南 看了一堆教程还是不会写项目?别慌,这很正常。 很多开发者卡在分页逻辑上,特别是处理“上一页”跳转时,边界条件没处理好,测试一跑就报错。 今天带你用实战代码,把… · 2026/9/23 14:47:03

Apache Flink DataStream 连接器全景指南:预定义源汇、官方连接器与接入方式详解
Apache Flink DataStream 连接器全景指南:预定义源汇、官方连接器与接入方式详解

Apache Flink DataStream 连接器全景指南:预定义源汇、官方连接器与接入方式详解 【免费下载链接】flink 项目地址: https://gitcode.com/gh_mirrors/fli/flink 导读 本文以 Apache Flink DataStream API 的连接器体系为核心,系统梳理 Flink 提… · 2026/9/23 14:47:03

TensorBoard 框架集成指南:PyTorch / TensorFlow / Lightning / Transformers 等多框架训练可视化实战
TensorBoard 框架集成指南:PyTorch / TensorFlow / Lightning / Transformers 等多框架训练可视化实战

AI 技能人工智能大模型深度学习 【免费下载链接】AI-Research-SKILLs Comprehensive open-source library of AI research and engineering skills for any AI model. Package the skills and your claude code/codex/gemini agent will be an AI research agent with full hor… · 2026/9/23 14:47:02

电工电子课程设计报告写作指南:从方案论证到误差分析
电工电子课程设计报告写作指南:从方案论证到误差分析

简介:这份电工电子课程设计报告面向电气电子类专业本科生,完整呈现家用智能控制系统相关的三个典型项目:非法入侵报警电路、节能灯控制电路及有害气体检测报警与抽排电路,适合用于课程设计参考、方案论证与期末报告撰写。内容按武… · 2026/9/23 14:46:56

DNF好感度在哪看踩坑实录与源码级完整示例
DNF好感度在哪看踩坑实录与源码级完整示例

DNF好感度在哪看踩坑实录与源码级完整示例 学会语法却不知怎么搭项目,是无数程序员从新手进阶时最大的拦路虎。很多人对着教程敲代码能跑通,但一换场景就抓瞎,不知道模块之间怎么交互,数据流又是怎么在底层传递的。今天咱们不聊虚的,直接以大家常问的… · 2026/9/23 14:46:56

2026最新umdbbs底层原理:3分钟吃透核心机制
2026最新umdbbs底层原理:3分钟吃透核心机制

2026最新umdbbs底层原理:3分钟吃透核心机制 官方文档翻了三遍还是云里雾里?别急,这太正常了。很多开发者一看到【umdbbs】的官方手册,直接就被那几千行的配置说明和抽象概念劝退,根本抓不住重点。其实,【umdbbs】的核心逻辑没那… · 2026/9/23 14:46:50

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码