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

时间:2017-10-02 15:29:22

标签: node.js testing mocha bdd chai

在过去的几个月里,我正在开发一个从头开始的大项目的后端(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";
  • 您有什么好的做法可以分享吗?
  • 是否有任何可用的npm软件包(或用于的软件包) 其他编程语言)?
  • 你认为这种做法也有缺点(比如混乱时) 会有多个进口)?
  • 也许有injectinherit test-suite的方法 每个文件,以避免导入并默认在每个文件中使用它?
编辑:忘记提及 - 我的意思是集成测试。

提前致谢!

1 个答案:

答案 0 :(得分:1)

重构当前测试套件

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

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

lastEmail = getLastEmailSent()

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

现在在实施这些方法时,可能会发生很多事情。特别是,registerUser函数可以执行发布请求(如您的示例中所示)。 getLastEmailSent可以从邮件队列或虚假SMTP服务器中读取。问题是你隐藏了API背后的细节。

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

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

我看到你提出的建议(提取RegisterUserAndGetJWTToken和测试数据)是创建自动化层的一个很好的步骤。我不会担心require电话。我没有看到任何理由不明确我们的测试取决于什么。也许在稍后阶段,其中一些可以收集在更大的模块中(registrationemailing等。)

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

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

    有时通过UI或REST会更好,但通常直接调用函数会更明智。例如,如果您编写一个用于计算发票上的税金的测试,则对每个测试用例进行整个应用程序测试将是一种过度杀伤力。离开一个端到端测试看看所有部分是否一起工作,并在尽可能低的级别自动化所有特定情况,这样会好得多。这样我们就可以获得良好的覆盖范围,以及测试套件的速度和稳健性。

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

    您可以参考this discussion获得一个很好的解释。

  3. 在处理生产代码时,请小心处理您的测试助手代码/自动化层。

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