# 单元测试

前端单元测试是指对前端代码中的每一个模块(函数、组件等)进行测试的过程。前端单元测试可以通过自动化测试工具(如JestMochaKarma等)来完成。其中,JestFacebook开源的单元测试框架,具有快速、易于学习和使用等特点,已成为前端测试的重要工具之一。

前端单元测试可以检测代码中每个模块的正确性和健壮性,可以确保代码在修改后不会影响到原有的功能实现,也有助于开发者找出程序中的错误、漏洞和缺陷。单元测试还可以促进代码重构,并提高代码的可读性和可维护性,同时也可以减少代码中的冗余和无用代码。

单元测试的质量好坏可以通过代码覆盖率来判断,而代码覆盖率由四部分组成:

  • 语句覆盖率(Statement Coverage) 用于衡量被测试代码中每条语句的执行覆盖情况
  • 行覆盖率(Line Coverage) 用于衡量被测试代码中每行代码的执行覆盖情况,不包含空行和注释等
  • 函数覆盖率(Function Coverage) 用于衡量被测试代码中每个声明函数的执行覆盖情况
  • 分支覆盖率(Branch Coverage) 用于衡量被测试代码中每一个判定分支的执行覆盖率

TIP

语句覆盖率和行覆盖率在定义上十分接近,很多资料都会将其画等号。在实际开发中,如果一行代码中只有一条可执行语句,此时语句覆盖率等同于行覆盖率。如果一行代码中有多条可执行语句,并且有存在执行语句执行不到的情况下,语句覆盖率和行覆盖率就不相同。

# 为什么需要单元测试

很多人会说,“前端需求变化这么快,单元测试没法做”。这句话有一定的道理,针对快速迭代的项目而言,业务逻辑一般会跟着项目迭代和更新随时变化,针对业务逻辑写单元测试的意义不大。但正因为项目快速迭代,所以对于公共组件和公共函数的要求更高,更需要去做单元测试来提高它们的可靠性和稳定性。

再次,当项目重构的时候,单元测试能有效保证代码重构前后逻辑的一致性,大大减少在测试环节中投入的精力。

开源社区的知名项目基本都有完善的单元测试,可以增强开发人员在工作中的可靠性和稳定性。代码覆盖率不仅代表了当前项目的质量,也一定程度上反应了维护者对他的精力和重视程度。

# 有单元测试代码质量就有保证吗

不是的,单元测试的代码覆盖率可以作为衡量项目质量的指标之一,但不是全部。因为代码覆盖率 100%只能保证代码的每个语句、分支都被运行过了,不能确保所有执行结果都符合预期。以下面的代码为例,add 是将两个数相加的函数,返回的结果是两个入参的和。

// add.js
function add(a, b) {
  return a + b;
}

// add.test.js
describe('add', () => {
  test('test'. () => {
    expect(add(1, 1)).toEqual(2);
  });
});
成功
1
2
3
4
5
6
7
8
9
10
11

使用 Jest 执行以上代码,输出的测试报告中的语句覆盖率、行覆盖率、函数覆盖率及分支覆盖率均为 100%。按照预期,执行以下函数,应该输出 true。

console.log (add(0.10,2) === 0.3)
成功
1

实际上,由于Javascript浮点数运算的精度原因,输出结果为false。代码覆盖率只能证明代码被测试过,不能证明代码的逻辑一定正确。除了代码覆盖率应尽量达到100%,单元测试还应该设计不同场景下的测试用例来尽量覆盖边界情况。

# 小结

通过前端单元测试,可以检测前端代码中的错误和缺陷,并确保代码的正确性和可靠性。同时,单元测试也帮助开发者更好地理解应用程序,并了解代码中的逻辑,从而更高效地开发和维护应用程序。但作为开发人员,我们不能过于相信单元测试的代码覆盖率,应该以辩证的眼光去看待。