# 最恶心的测试用例--现实生活中的反模式测试行为


看到一篇吐槽测试用例的文章https://itnext.io/the-worst-test-suite-testing-anti-patterns-experienced-in-real-life-24fd13ee3ddd，觉得挺有意思的，没啥新意，不过也确实是我们会遇到的问题，或者说是我们生活的一部分。顺手翻译了一下，下面是文章内容。

我认为这里不需要介绍，我将告诉您我遇到的最糟糕的测试套件(testsuit)是什么样子，以及它是如何运作的。

我提前警告您，这篇文章会让您感到恶心，皮肤发痒，工程技能受挫。

我将介绍的反模式将以恶心程度进行排名，从 🤮 表示糟糕到 🤮🤮🤮 表示完全不可原谅。
所有的反模式都很糟糕，但其中一些我从未在其他地方见过，我认为对它们进行排名将强调它们的隐蔽性。

在阅读本文时，整个套件大约有 10 个测试文件。其中 9 个是“合理的”，第十个则是一场噩梦：它有大约 3000 行代码，总共组合了约 80 个测试用例。测试套件的约 95%都在这个文件中。

除了测试用例之外，测试使用的所有工具都散落在这个文件中。

### 混合测试类型

恶心程度: 🤮

该文件包含了许多不同类型的测试——从单元测试到组件测试，再到端到端测试。有些测试非常难以确定测试类型——有些单元测试通过运行系统的主要部分来测试特定的小功能，而在其他情况下，通过调用系统的内部功能序列来执行主要的端到端测试。

### 为什么测试被编号？

恶心程度: 🤮🤮🤮

所有的测试名称都被编号了！所有的测试都采用了 TestXX_what-the-test-checks 的形式。

这是一个重要的警示信号，当我加入这个项目时，我没有完全意识到它的重要性。大约工作了两个月后，显然这些测试之间的顺序是有问题的！这些数字是为了强制排序而存在的。这些测试是相互依赖的。

不用说，当我移动一些测试以使那个庞大的文件变得更清晰时，我是以艰难的方式学到了这一点。

如果我想添加一个测试，它必须与其他测试正确排序。这创造了一种荒谬的情况，我必须正确命名测试以便按正确的顺序运行。因此，如果我想让一个测试在 Test34_XXX 和 Test34_YYY 之间运行，我必须将我的测试命名为 Test341_ZZZ，以确保字典顺序正确 🤯

### 匿名测试

恶心程度: 🤮

关于测试名称，还有一件事——其中一些是匿名的——这些测试并没有说明它们实际覆盖的内容，例如：test19_requirement_59_passes 或者最受欢迎的 test87_process_works。

有些测试只有在我引入了使它们失败的更改后，我才知道它们测试的是什么，这迫使我进行调查工作以弄清楚它们在做什么。

(这不是原文，这只是我的补充：这种情况就是测试用例的名字没有任何的意义，没人知道这个用例在做什么)

### 断言？它们只是建议

恶心程度: 🤮🤮🤮

一些测试没有以断言结束。您当然会问一个没有断言的测试在做什么？

在这些测试中，测试的顶部有一条注释，指示“用户”去做某事。通常是像“转到日志文件并检查是否存在格式为 X - Y - Z 的日志消息”。

不用说，这并没有说明日志文件在哪里，如果有多个文件（由于日志轮换配置）该怎么办。而且，在某些情况下，这些说明已经过时，日志消息自“测试”和其说明编写以来已经发生了变化。

这些测试显然总是通过的，项目移交期间没有人告诉我这些事情，我是在添加一个功能时偶然发现有一个测试，其名称表明它测试的是我实现的过时功能的相反面。它显然通过了（因为它没有断言）。

我删除了所有这些测试，再也没有回头看过。

(这不是原文，这只是我的补充：这种情况就是只执行动作不做断言，基本上大部分同学入门的时候都会经历这个阶段。)

### 复杂和隐晦的输入

恶心程度: 🤮

系统的测试输入相当复杂，大多数测试都基于一个单独的输入文件。除了“刚好足够让测试通过”的输入之外，它包含的内容相当隐晦。没有人真正记得这个测试文件是如何创建的。

为了将每个测试带到相关状态，散布在 3000 行代码中，有一些实用方法来操作输入文件。它们都没有解释它们的作用，通常被称为 prepare_for_test78 之类的名称。

每当我们需要更改输入时，我们都会有点儿心痛 🥲

(这不是原文，这只是我的补充：这种情况就是准备的数据不具备可读性，没人知道这些数据是做什么的。)

### 拖累的共享状态

🤮 恶心程度: 🤮🤮

不仅测试彼此相互依赖，被测试的系统本身也在测试之间拖累了一些内部状态。

原始作者没有在每个测试之前重新创建系统，而是添加了一组方法，使测试驱动程序能够将内部状态置为 null。

### 入口不明确

恶心程度: 🤮🤮

有一些测试调用了内部函数，并按照特定顺序调用——实际上很难确定测试的入口是什么。事实证明，所有这些调用的函数散布在不同的类中，影响了一些最终被测试的内部共享状态。

### 最后的思考

是的，这是一个真实的故事。
是的，有点夸张，但只是一点点。

我不知道这个测试套件是如何变得如此糟糕的，但我认为只是出于善意。

这个项目在很长一段时间内处于 POC 阶段，并且直到后期才成为任何人关注的焦点或优先事项，这可能可以解释，但我不知道。

幸运的是，被测试的系统相对简单。除了复杂的输入之外，逻辑本身并不太难理解和推理。这使得在这些条件下工作成为可能。
如果系统稍微复杂一些，情况可能会更糟。

话虽如此，也许系统足够简单是导致测试套件变得如此糟糕的原因？

我们尽力改善情况，但我们主要是尽量不要让情况变得更糟。所有新开发的内容都要符合更高的标准，我们决定尽量少地添加到“厄运之一文件”中。

尽管如此，这次经历对我来说是一所了不起的学校——我学到了不应该做什么，以及做这些事情的影响。就像得了一次非常严重的肺炎，才明白在寒冷的冬天穿着 T 恤出门是不应该的。

