文章介绍了 Move 生态中的 Mutation Testing 工具 Move Mutation Tester,它通过自动修改源码生成多个“突变体”,再运行原有单元测试来判断测试是否能发现这些故障。

对于处理高价值资产的合约来说,穷尽式测试至关重要。但你怎么知道测试是否已经足够好了呢?Move Mutation Tester 是 Move 工具集中的一款新工具,它可以自动发现测试套件中的盲点。
良好的单元测试对于确保软件正确性和体现预期行为非常重要。事实上,它们是现代软件工程中的常见实践。要以高度信心演进软件,单元测试也必不可少:即在修改代码(添加新行为或修复 bug)时,不会破坏原有的预期行为。在智能合约领域,良好的单元测试甚至更加重要,因为有缺陷的代码可能会带来严重的财务后果。
衡量代码覆盖率是评估单元测试质量的主要方法。Aptos CLI 提供了一个 coverage 工具,我们建议将其作为最佳实践使用。然而,代码覆盖率只能衡量某一行代码是否被单元测试覆盖,却不能衡量单元测试是否对被测代码执行了正确的语义检查。在之前的一篇博客中,我们展示了为什么代码覆盖率不足以衡量单元测试的质量。
Mutation testing 是一种用于发现单元测试盲点的技术,其能力远不止覆盖率工具。它会在源代码中注入故障,并检查单元测试是否能够检测到这些故障。我们现已发布 move-mutation-test 工具的首个版本(可在这里获取,由我们在 Eiger 的合作伙伴开发)。它可以评估 Move 单元测试的质量,我们非常希望你能在自己的 Move 项目中试用它,并向我们反馈。
该工具分两步运行:
如果 mutation test 工具的报告中存在大量存活 mutant,那么就值得考虑改进单元测试。
你可以使用 aptos update move-mutation-test 安装该工具(请确保使用最新的 aptos CLI,至少为 7.0.0 版本)。另外,你也可以从源码安装。
让我们在一个真实项目中做一个小练习,看看该工具可以如何使用。我们将使用 aptos-stdlib 项目。
该工具有两个主要子命令:
move-mutation-test run(运行工具并生成报告),move-mutation-test display-report(以更友好的方式展示结果)该工具可以为整个项目生成大量 mutant,并且对每个 mutant 运行测试可能相对较慢。推荐的使用方式是更有针对性一些,也就是按模块或按函数分别使用。
让我们选择 fixed_point64 模块来生成 mutant。为了避免生成那些由于缺少单元测试覆盖而必然存活的 mutant,我们使用 --coverage 标志,以确保只在具有适当单元测试覆盖的代码部分生成 mutant。
记住我,以便更快登录
注意:要使用 --coverage 标志,用户首先需要运行 aptos move test --coverage 命令,在项目文件中本地生成单元测试 coverage 报告。下面我们假设该命令已经运行过。
move-mutation-test run --coverage --output report.txt --mutate-modules fixed_point64

该命令执行完成后,我们应该会看到一个简短的摘要,告诉我们该模块中每个函数的存活 mutant 数量。

从上面的报告中,我们可以看到,函数 round 有九个存活 mutant。让我们使用以下命令更详细地查看结果:
move-mutation-test display-report coverage --path-to-report report.txt

如果继续向下滚动,就会找到 round 函数,在那里我们可以看到 mutation testing coverage:也就是包含 killed/total mutants 信息的那些行:

请注意,理想情况下是让所有或大多数 mutant 都被杀死。这只是该函数 mutation testing coverage 的一个简单概览,但它并不能告诉我们哪些 mutant 存活了。为此,我们可以使用 mutants 子命令:
move-mutation-test display-report mutants --modules fixed_point64 --functions round

接下来,让我们看看如何改进单元测试,使这些 mutant 能够导致测试失败。

从上面可以看出,round 函数的测试还可以进一步改进。让我们尝试用下面的内容来增强这些测试:

现在,我们可以重新运行该工具。这次让我们更具体一些,以缩短执行时间,并使用以下命令只对 round 函数进行 mutation:
move-mutation-test run --coverage --output report.txt --mutate-modules fixed_point64 --mutate-functions round

我们已经可以从摘要报告中看到,这个函数的统计数据有所改善!
让我们再次使用 display-report coverage 命令检查 coverage:
move-mutation-test display-report coverage

现在,mutation testing 的 coverage 已经提升了(更多 mutant 被杀死),从而提高了测试的质量。
上面的输出类似于单元测试 coverage 报告。它展示了每一行中 killed mutants 数量占总 mutants 数量的统计信息。
Mutation testing 是对代码 coverage 工具的补充,有助于深入了解单元测试的质量。它可以发现单元测试中的盲点,从而也有可能识别源代码中的 bug。我们建议尝试使用它,尤其适用于高保证的 Move 合约。
请注意,就像在所有地方都努力达到 100% 的代码覆盖率可能并不值得(有时甚至会适得其反,因为这会使单元测试过于脆弱)一样,达到 100% 的 mutation testing coverage 也可能让你误入歧途。mutation testing 的结果应作为指导,并结合项目本身的判断,来识别代码库中哪些部分应获得更多关注,以改进测试。
- 原文链接: medium.com/aptoslabs/mut...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!