# 单元测试

# 导航

  • 什么是单元测试
  • 单元测试和集成测试有什么区别?
  • 你知道哪些前端单元测试框架?它们有什么优缺点?
  • 如何进行测试驱动开发(TDD)?
  • 如何编写具有可测试性的代码
  • 如何对异步代码进行单元测试?
  • 如何测试 React 组件?
  • 如何模拟用户交互行为进行测试?
  • 什么是覆盖率?如何计算代码的覆盖率?
  • 你如何集成单元测试到 CI/CD 流程中?
  • 什么是 Jest 的快照测试?
  • Jest 如何模拟异步请求?
  • Jest 如何使用 Mock 函数?
  • 如何在 Jest 中使用 ES6 模块?
  • Jest 可以与哪些持续集成工具集成?

# 什么是单元测试

单元测试是指对软件系统中最小的可测试单元进行验证和测试的过程。单元测试通常是指对一个模块、函数或方法进行测试,以确保其满足预期的行为和功能。

单元测试优点

  1. 可以保证代码的质量:单元测试可以检测代码中的潜在问题,如边界条件、错误处理和异常情况等,从而可以在开发过程中及早地发现和修复问题,减少后期维护成本。
  2. 提高代码的可维护性:在开发过程中,单元测试可以帮助开发人员了解代码的工作原理和逻辑,从而更容易进行维护和修改。
  3. 加速开发过程:单元测试可以提高代码的质量和可维护性,从而减少后期维护成本,加快开发过程的进度。
  4. 支持重构和改进:单元测试可以验证代码的行为是否正确,从而使开发人员更加自信地对代码进行重构和改进。
  5. 提高代码的可重复性:单元测试可以确保代码的行为和功能符合预期,从而提高代码的可重复性和稳定性。

集成测试

集成测试(Integration Testing)是软件测试的一种类型,是指将多个模块或组件组合在一起进行测试,以验证它们之间的接口和交互是否正确,以及整个系统是否符合预期的行为和功能。

# 如何编写具有可测试性的代码

编写具有可测试性的代码是软件开发的一个重要方面,它可以帮助开发人员更容易地编写和执行自动化测试用例,从而提高代码质量和可维护性。下面是一些编写具有可测试性的代码的建议:

  1. 设计清晰的接口:将代码分解为独立的模块或组件,并定义清晰的接口和抽象层次结构,以便能够对每个模块或组件进行单独测试。
  2. 使用依赖注入:使用依赖注入(Dependency Injection)技术将组件之间的依赖关系解耦,并将依赖关系从代码中分离出来,从而更容易进行测试。
  3. 编写可读性高的代码:编写可读性高的代码可以使测试用例更易于编写和维护,并且可以使测试结果更加清晰和明确。
  4. 编写短小精悍的方法:编写短小精悍的方法可以使测试用例更加容易编写和维护,从而提高代码的可测试性。
  5. 使用模拟对象:使用模拟对象(Mock Object)可以模拟实际的依赖关系,并使测试更容易进行。
  6. 遵循设计模式:使用设计模式可以提高代码的可测试性,并将代码分解为更小的单元,以便更容易进行测试。
  7. 遵循最佳实践:遵循最佳实践可以提高代码的可测试性,例如,遵循单一职责原则、开闭原则、里氏替换原则等。

总的来说,编写具有可测试性的代码需要良好的设计和编码实践,以便能够将代码分解为可测试的单元,并使用合适的工具和技术进行测试。

# 什么是覆盖率?如何计算代码的覆盖率?

代码覆盖率是指代码中被测试用例覆盖到的代码行数和总代码行数的比例。

  • 在项目根目录下创建一个 jest.config.js 文件,并添加以下内容,其中 collectCoverage 表示开启代码覆盖率统计,collectCoverageFrom 表示统计哪些文件的代码覆盖率。
module.exports = {
  collectCoverage: true,
  collectCoverageFrom: ["src/**/*.{js,jsx,mjs}"]
}
  • package.json 文件中的 scripts 中添加以下内容 "test": "jest --coverage"
  • 运行 npm testyarn test 命令,Jest 将会执行测试并输出代码覆盖率报告

另外

计算代码覆盖率可以帮助开发人员了解哪些代码被测试用例覆盖到,哪些代码没有被覆盖到,从而更好地了解代码质量和测试覆盖的程度。这可以帮助开发人员优化代码和测试用例,提高代码可维护性和可测试性。

  • % Stmts:语句覆盖率,即所有代码语句中被测试用例覆盖到的语句所占比例。
  • % Branch:分支覆盖率,即所有条件分支语句(如 if)中被测试用例覆盖到的分支所占比例。
  • % Funcs:函数覆盖率,即所有函数中被测试用例覆盖到的函数所占比例。
  • % Lines:行覆盖率,即所有代码行中被测试用例覆盖到的行所占比例。
  • Uncovered Line #s:未覆盖行号,即哪些代码行没有被测试用例覆盖到。