Test Behaviors, Not Methods! Detecting Tests Obsessed by Methods
本文提出了一种名为“方法痴迷型测试”(Test Obsessed by Method)的新型测试异味,该异味识别了覆盖单个生产方法内多个执行路径的测试,并通过对 Python 标准库的实证研究验证了其检测能力,研究表明此类测试通常验证了多种行为,并且可以重构为更专注的单元。
原始论文采用 CC BY 4.0 许可(http://creativecommons.org/licenses/by/4.0/)。 这是对下方论文的AI生成解释。它不是由作者撰写或认可的。如需技术准确性,请参阅原始论文。 阅读完整免责声明
想象一下你是一位正在为美食评论家准备品鉴菜单的大厨。烹饪的一条金科玉律是:每道菜只呈现一种独特的风味。 如果你在一个盘子里混在一起盛放牛排、蛋糕片和冰淇淋,评论家就会感到困惑。他们无法判断是牛排没熟、蛋糕太甜,还是冰淇淋化了。如果出了问题,他们不知道该归咎于哪一部分。
在软件世界中,“菜肴”是测试,而“风味”是行为(即软件应该执行的功能)。
这篇题为《测试行为,而非方法!》(Test Behaviors, Not Methods!)的论文指出,许多软件测试目前就像这种混乱的混合盘。作者 Andre Hora 和 Andy Zaidman 引入了一种新的方法来识别这些令人困惑的测试,他们称之为**“被方法所痴迷的测试”**(Tests Obsessed by Methods)。
以下是他们利用简单类比对这一发现进行的拆解:
1. 旧方法:计算食材数量
此前,专家们试图通过计算一个测试“触碰”了多少次代码来寻找这些混乱的测试。他们认为:“如果一个测试调用了生产代码 3 次或更多次,它可能做得太多了。”
作者称这种现象为**“急躁测试”**(Eager Test)的气味。然而,他们发现这种方法就像仅仅通过数使用了多少把勺子来评判一顿饭一样。这并不准确。一个测试可能会为了搭建场景而多次调用某个函数,但并没有实际测试不同的风味。这是一种笨拙的寻找问题的方法。
2. 新思路:观看电影(运行时分析)
与其仅仅计数勺子的数量,作者建议观察测试播放时的“电影”。他们提出了一个新规则:如果单个测试迫使一段代码在到达终点前走过多条不同的“道路”(路径),那么这个测试就是“痴迷”的。
把一段生产方法(一段代码)想象成一个迷宫。
- 好的测试: 你派出一名探险家进入迷宫,检查左边的门是否可行。然后你派出第二名探险家,去检查右边的门是否可行。清晰且专注。
- 痴迷的测试: 你派出一名探险家,他先走左边的门,然后折返,再走右边的门,接着又尝试秘密通道,这一切都在一次行动中完成。
作者称之为**“被方法所痴迷的测试”**。这个测试是“贪婪”的,因为它试图在一个过程中覆盖单个迷宫的所有可能路径,而不是将工作拆分开来。
3. 实验:检查 Python 库
为了验证这种“痴迷”是否是一个真实存在的问题,作者在 Python 标准库(一个被数百万开发者使用的庞大预写代码集合)中进行了一场寻宝游戏。
他们检查了 2,054 个测试。以下是他们的发现:
- 搜寻过程: 他们发现了 44 个“痴迷”的测试。这些测试试图在一次运行中检查单个函数的多个不同结果。
- 分布情况: 这些混乱的测试出现在他们检查的 12 个库中的 11 个里。这并非罕见的故障,而是一种常见的习惯。
- 修复方案: 平均而言,这 44 个混乱的测试实际上都在尝试做两件不同的工作。如果将它们拆分,这 44 个测试可以变成 118 个清晰、专注的测试。
- “恍然大悟”的时刻: 在大约 23% 的这些混乱测试中,程序员竟然在注释里承认:“嘿,我们这里正在测试两件事!”他们知道这很混乱,但还是照做了!
4. 为什么这很重要?
作者认为,当一个测试试图同时覆盖太多路径时:
- 难以理解: 就像那个混合盘,你无法分辨自己尝到的是什么味道。
- 脆弱性高: 如果你修改了“左门”的代码,你可能会意外破坏“右门”的测试,尽管它们之间并无关联。
- 难以修复: 当测试失败时,你无法知道具体是哪种行为出了问题。
核心结论
该论文并不声称解决了所有的测试问题。相反,它提供了一个更锐利的工具(使用运行时分析而非仅仅计数)来识别那些试图用单段代码完成过多工作的测试。
他们建议,如果一个测试迫使一个函数走向多条不同的路径,就应该将其拆分。就像大厨应该将牛排、蛋糕和冰淇淋分别盛放在不同的盘子里一样,开发者也应该为每种不同的行为编写独立的测试。
简而言之:不要对你的测试过于贪婪。一次测试一种行为,一条路径,一种风味。
您所在领域的论文太多了?
获取与您研究关键词匹配的最新论文每日摘要——附技术摘要,使用您的语言。