前端单元测试入门实践(上)

发表于:2024-1-10 09:41

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:黄成翰    来源:稀土掘金

  前端单元测试
  简介前端单元测试是指对前端代码中的最小可测试单元进行测试的过程。这些最小单元可以是函数、组件或模块等。通过编写针对这些单元的测试用例,我们可以验证它们在各种情况下的行为是否符合预期。
  单元测试从概念上可以分为:
  ·TDD (Test-Driven Development):测试驱动开发
  · BDD (Behavior-Driven Development):行为驱动开发
  TDD
  TDD 强调在编写实际代码之前先编写测试用例。TDD的核心理念是通过编写测试来指导代码的开发,以确保代码的正确性和可靠性。TDD的工作流程通常包括以下步骤:
  ·编写测试用例:首先,开发者根据需求或功能规范编写一个测试用例。这个测试用例描述了期望的行为和结果。初始时,由于尚未编写任何实际代码,所以测试用例会失败。
  · 运行测试用例:接下来,开发者运行测试用例,确认它们失败。这是因为尚未编写与测试用例相匹配的实际代码。
  · 编写实际代码:在测试用例失败的基础上,开发者开始编写实际的代码,以满足测试用例中所描述的需求。目标是使得测试用例能够通过并成功执行。
  · 运行测试用例并重构:一旦实际代码编写完成,开发者再次运行测试用例。如果测试用例通过,说明代码已经正确实现了需求。此时,开发者可以进行代码重构,改进代码的结构、可读性和性能,同时确保测试用例仍然通过。
  编写单元测试的意义
  · 提高代码质量:通过测试用例覆盖率和错误检测,我们可以及早发现并修复潜在的问题,从而提高代码的质量。
  · 简化调试过程:当出现问题时,单元测试可以帮助我们快速定位错误所在,并且在修复后能够确保不会再次出现同样的问题。
  · 支持重构和维护:在进行代码重构或修改时,单元测试可以帮助我们确保改动不会破坏原有功能。
  · 促进团队协作:通过编写单元测试,团队成员可以更好地理解彼此的代码,并共享对代码行为的理解,从而促进团队协作。
  如何进行单元测试
  简单尝试
  第一步,用你最喜欢的包管理工具安装测试框架Jest。
  npm install --save-dev jest
  我们现在可以写一个简单的demo来试试水,找个空地创建名为sum.js的文件。
  function sum(a, b) {
    return a + b;
  }
  module.export = sum;
  显然这是个提供计算两数之和(或拼接字符串)能力的模块。如果不使用单元测试框架,我们会通过把代码跑起来打日志这种朴素的方法去验证它的正确性,现在我们可以创建sum.test.js文件来对其进行验证。
  const sum = require('./sum');
  describe('sum.js', () => {
    test('两数之和', () => {
      expect(sum(1, 2)).toBe(3);
    });
    it('字符串拼接', () => {
      expect(sum('a', 'b')).toBe('ab');
    });
  });
  在package.json中添加
  {
    "scripts": {
      "test": "jest"
    }
  }
  运行
  npm run test
  如果一切正常,Jest将输出如下信息:
  测试文件由许多测试用例组成,Jest通过test方法(或与其等价的it方法)执行测试代码,在上述demo中,我们编写了两个测试用例,验证了sum方法的正确性。
  支持ES6语法
  Jest是执行在Node环境的,Node.js采用CommonJS模块化规范,通过require引入模块,如果要使用import这类ES6模块化规范的语法,必须借助babel来转义支持。
  安装babel相关依赖
  npm install --save-dev @babel/core @babel/preset-env
  在根目录下配置babel,创建.babelrc
  {
    "presets": [
      "@babel/preset-env"
    ]
  }
  现在我们可以自由使用ES6的模块化语法了。
  function sum(a, b) {
    return a + b;
  }
  export sum;
  import { sum } from './sum';
  describe('sum.js', () => {
    test('两数之和', () => {
      expect(sum(1, 2)).toBe(3);
    });
    test('字符串拼接', () => {
      expect(sum('a', 'b')).toBe('ab');
    });
  });
  原因是Jest运行时内部会先执行jest-babel检测是否安装babel-core,然后获取.babelrc中的配置,在运行测试文件前用babel将其转换为支持的语法再执行测试。
  使用TypeScript
  如果要对TypeScript文件进行单元测试,需要额外安装依赖,借助babel去解析TypeScript文件再进行测试。
  npm install --save-dev @babel/preset-typescript
  在.babelrc中添加对应配置
  {
    "presets": [
        "@babel/preset-env",
      "@babel/preset-typescript"
    ]
  }
  如果使用如VSCode之类的编辑器,为了解决其对Jest断言方法类型的报错,还需额外安装@types中的第三方类型库。
  npm install --save-dev @types/jest
  目录结构
  测试文件一般以.test.js/ts为尾缀,通常放在根目录下的test文件夹内。
  不过现在更推荐放在被测试的源代码旁边,这样做有很多好处,其一是方便查找,其二是方便管理,当废弃某个组件或模块是,与其有关的所有垃圾文件(包括测试代码)方便一并废弃。
  简单配置
  尽管Jest做到了开箱即用,但有时我们仍想自定义某些配置,此时可以通过执行。
  ## 全局安装时
  jest --init
  ## 局部安装时
  npx jest --init
  生成基础配置。每个字段的具体含义,可以参阅官方文档。
  测试覆盖率
  单元测试的覆盖率是指所有功能代码中完成单元测试的代码所占的比例,可以反映测试用例的全面性与被测试代码的可靠性。测试覆盖率由语句覆盖率、函数覆盖率、分支覆盖率和行覆盖率所量化。
  ·Statements(语句覆盖率)
  是否每个语句都执行了
  · Branches(分支覆盖率)
  是否每个判断都执行了
  · Functions(函数覆盖率)
  是否每个函数都执行了
  · Lines(行覆盖率)
  是否每行都执行了
  我们可以通过如下配置来查看每个测试用例的测试覆盖率以及自定义覆盖率阈值。
  module.exports = {
    // 是否显示测试覆盖率报告
    collectCoverage: true,
    // 哪些文件需要被执行单元测试
    collectCoverageFrom: [
      'src/utils/**/*'
    ],
    extensionsToTreatAsEsm: ['.tsx', '.jsx', '.ts'],
    // 测试覆盖阈值
    coverageThreshold: {
      global: {
        statements: 90, // 保证90%的语句都执行了
        functions: 90, // 保证90%的函数都调用了
        branches: 60, // 保证60%的 if 等分支代码都执行了
      },
    },
  }
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号