如何在大量 Node.JS BDD 测试中避免代码冗余

How to avoid code redundancy in large amounts of Node.JS BDD tests

在过去的几个月里,我一直在为一个我们从头开始的大型项目的后端 (REST API) 工作。我们遵循 BDD(行为驱动开发)标准,所以现在我们有大量测试(~1000)。测试是使用 chai 编写的 - Node.JS 的 BDD 框架,但我认为这个问题可以扩展到编写测试时的一般良好实践。

起初,我们尽量避免代码冗余,而且进展顺利。随着代码行数和从事该项目的人员的增加,它变得越来越混乱,但可读性却越来越差。有时可以在 15 分钟内应用的代码中的微小更改导致需要更改,例如30 多个文件等中的模拟数据和方法,这意味着 6 个小时的更改和 运行 测试(极端示例)。

TL:DR

我们现在想重构这些 BDD 测试。例如我们有这样一个函数:

function RegisterUserAndGetJWTToken(user_data, next: any){
    chai.request(server).post(REGISTER_URL).send(user_data).end((err: any, res: any) => {
        token = res.body.token;
        next(token);
    })
}

我们的大部分测试文件都使用了这个函数。创建包含此类函数的 test-suite 之类的东西是否有意义,或者在编写测试时是否有更好的方法来避免冗余?然后我们可以使用像这样的导入:

import {RegisterUserAndGetJWTToken} from "./test-suite";
import {user_data} from "./test-mock-data";

编辑:忘记提及 - 我的意思是集成测试。

提前致谢!

重构当前测试套件

您的原则应该是提高测试本身的抽象级别。这意味着测试应该包含用领域语言表达的高级方法调用。例如:

registerUser('John', 'john@smith.com')

lastEmail = getLastEmailSent()

lastEmail.receipient.should.be 'john@smith.com'
lastEmail.contents.should.contain 'Dear John'

现在在这些方法的实施过程中,可能会发生很多事情。特别是, registerUser 函数可以执行 post 请求(如您的示例)。 getLastEmailSent 可以从消息队列或伪造的 SMTP 服务器中读取。问题是你隐藏了 API.

背后的细节

如果您遵循这一原则,您最终会创建一个自动化层 - 一个面向领域的、程序化的 API 到您的系统。创建这一层时,您遵循所有良好的设计原则,例如 DRY。

好处是,当代码发生变化时,测试代码中只有一个地方需要更改——在自动化层中,而不是在测试本身中。

我看到您提出的建议(提取 RegisterUserAndGetJWTToken 和测试数据)是朝着创建自动化层迈出的良好一步。我不会担心 require 电话。我看不出有什么理由不明确说明我们的测试依赖什么。也许在稍后阶段,其中一些可以收集到更大的模块中(registrationemailing 等)。

可维护测试套件的良好实践

  1. 在适当的级别实现自动化。

    有时通过 UI 或 REST 会更好,但通常直接调用函数会更明智。例如,如果您编写一个计算发票税金的测试,那么为每个测试用例遍历整个应用程序就太过分了。最好留下一个端到端测试,看看所有部分是否一起行动,并在尽可能低的级别上自动化所有特定案例。这样我们就可以获得良好的覆盖率,以及测试套件的速度和稳健性。

  2. 编写测试的指导原则是可读性。

    你可以参考this discussion的解释。

  3. 像对待生产代码一样谨慎对待测试助手代码/自动化层。

    这意味着您应该非常小心地重构它,遵循所有良好的设计原则。