likes
comments
collection
share

JavaScript测试的代码覆盖率

作者站长头像
站长
· 阅读数 27

JavaScript测试的代码覆盖率 代码覆盖率(Code Coverage)在测试中一个非常重要的指标,它可以帮助来衡量测试的质量,一般来说,代码的有效覆盖率越高越好;它也可以反过来衡量代码本身,如果一段代码永远都无法用合理的测试案例覆盖,那么它有可能是一段冗余的代码。

JavaScript代码覆盖率的指标

  • Bytes 字节覆盖率,仅原生V8覆盖率支持
  • Statements 语句覆盖率
  • Branches 分支覆盖率,比如if,switch这些
  • Functions 函数覆盖率
  • Lines 行覆盖率

两种JavaScript代码覆盖率的数据格式

  • V8 coverage - JS V8引擎原生支持的覆盖率数据格式
    • 优点 - 原生支持,无需预编译,性能高; 支持CSS的覆盖率;支持压缩的代码;
    • 缺点 - 由于是使用V8引擎,所以支持Nodejs以及基于Chromium的浏览器;对源码需sourcemap支持(sourcemap本身由不同的编译工具生成,存在一些不确定性);然后就是V8覆盖率数据本身仅包含Bytes字节覆盖指标,和部分functions覆盖指标,其他指标需分析AST进行计算;
  • Istanbul - 老牌js覆盖率支持工具所支持的格式
    • 优点 - 支持所有JS运行环境,收集覆盖率数据简单,运行时将自动累加统计;除了Bytes指标,其他都支持;
    • 缺点 - 需要预编译源代码,将代码统计的计数器代码逐行插入源代码中,所有代码量大的时候,速度较慢;同样有对源码的sourcemap支持的问题,尤其是一些vue,xml等一些非原生js语法的代码;然后就是不同的编译工具,它需要专门的解析器,比如babel-plugin-istanbul vite-plugin-istanbul等等,可能导致格式混乱等问题;

主流测试工具的代码覆盖率支持情况

测试框架类型自带代码覆盖率报告支持数据源
Playwrighte2eV8
Puppeteere2eV8
Cypresse2eIstanbul
CodeceptJSe2eV8
WebdriverIOe2eIstanbul
Storybook Test Runnere2eIstanbul
TestCafee2e
Selenium Webdrivere2e
JestunitIstanbul/V8
VitestunitIstanbul/V8
Mochaunit/e2e

2024年如何选择测试工具?

如何解决Playwright的代码覆盖率报告

Playwright自动化测试工具@playwright/test并没有官方提供生成代码覆盖率报告的功能,但提供了收集V8覆盖率数据的接口,也就是可以通过使用第三方工具解决,这里推荐使用工具monocart-coverage-reports,下面简称MCR

  • 1,首先,使用MCR创建一个代码覆盖率报告实例
const MCR = require('monocart-coverage-reports');
const mcr = MCR({
    name: 'My Coverage Report - 2024-04-30',
    outputDir: './coverage-reports',
    reports: ["v8", "console-details"],
    cleanCache: true
});
  • 2,然后,需要在每个测试阶段开始之前,开启浏览器的V8 Coverage覆盖率数据收集
await Promise.all([
    page.coverage.startJSCoverage({
        // reportAnonymousScripts: true,
        resetOnNavigation: false
    }),
    page.coverage.startCSSCoverage({
        // Note, anonymous styles (without sourceURLs) are not supported, alternatively, you can use CDPClient
        resetOnNavigation: false
    })
]);
  • 3,接着,在测试阶段完成的时候,收集V8覆盖率数据,并将数据添加到覆盖率报告MCR中
const [jsCoverage, cssCoverage] = await Promise.all([
    page.coverage.stopJSCoverage(),
    page.coverage.stopCSSCoverage()
]);

const coverageData = [... jsCoverage, ... cssCoverage];
await mcr.add(coverageData);
  • 4,最后,在所有测试完成的时候,调用MCR的generate接口生成代码覆盖率报告
await mcr.generate();

测试报告将保存到步骤1中指定设置的位置,2和3的步骤可能调用多次

以上是基本的代码覆盖率报告生成逻辑,如何与Playwright集成呢?

集成MCR到Playwright

  • 因为playwright默认就是多任务并行的,所以我们可以使用playwright的autoTestFixture来自动收集和添加覆盖率数据,也就是上面的步骤2和3
  • 然后创建全局的回调 global.setup 和 global-teardown 来完成步骤1和4

完整的例子可见仓库:playwright-coverage

Playwright如何支持前后端代码的覆盖率报告?

就以时下流行的Nextjs框架为例,它是一个基于React的前后端代码一起写的框架,同一个文件的代码有可能有的在前端运行,有的在后端运行。那么当测试完成的时候,我们如何能得到整个代码的覆盖率情况?

// next.config.js
const nextConfig = {
    webpack: (config) => {
        if (process.env.NODE_V8_COVERAGE) {
            Object.defineProperty(config, 'devtool', {
                get() {
                    return 'source-map';
                },
                set() {}
            });
        }
        return config;
    }
};
export default nextConfig;
  • 然后使用下面两个环境变量来运行next dev
// package.json
"scripts": {
    "test:start": "cross-env NODE_V8_COVERAGE=.v8-coverage NODE_OPTIONS=--inspect=9229 next dev",
}

NODE_V8_COVERAGE是指定收集的后端v8覆盖率数据存储位置 NODE_OPTIONS是开启Nodejs调试,用于何时停止收集后端覆盖率数据

  • 前端代码的覆盖率收集就使用上面常规的方法,1,2,3步骤
  • 对于后端代码,由于已经使用NODE_V8_COVERAGE开启了收集,但还需要在global-teardown的时候来手动停止收集并写入硬盘目录,否则playwright全部测试完成后,会是强制关闭后端进程,导致后端覆盖率数据来不及写入硬盘

完整的例子可见仓库:nextjs-with-playwright

如何合并单元测试和端对端自动化测试的代码覆盖率报告?

在实际的项目开发中,我们多数情况是单元测试和自动化测试并存的,因为单元测试很多时候无法覆盖到一些整合的情况,还有一些需要交互情况,比如用户点击鼠标按键盘,拖动等等,这里就需要e2e自动化测试补充。如果使用Jest完成了单元测试,然后又用Playwright完成了e2e的测试,那么我怎么能知道整个代码的覆盖率情况呢? 下面以MCR工具为例来实现如何合并覆盖率报告:

  • 首先需要分别导出raw格式的覆盖率报告
  • 比如Jest我们可以使用jest-monocart-coverage插件来导出raw格式覆盖率报告
  • Playwright使用上面集成MCR的方法也同样导出raw格式覆盖率报告
  • 最后使用MCR支持的inputDir参数导入2个raw的报告来合并unit和e2e的报告

关于合并代码覆盖率报告的代码例子见:merge-coverage-reports

总结

JavaScript的代码覆盖率非常重要,但目前对于绝大多数国内公司,不论项目大小,一般都没有花功夫去支持。主要原因是不够重视测试和代码质量,还有就是成本高成效低。相对来说,国外的公司会更加的注重测试和质量一些。

其实以我个人的经验来说,使用了对的工具,其实还是比较容易建立起一套测试和质量保障体系的。无论是单元测试还是自动化测试,长久看它更多的保障了代码的质量,反而是更加节约成本的,很多改动带来的问题可以扼杀在摇篮里。希望上面的关于代码覆盖率的介绍能帮到你,也欢迎留言交流。

转载自:https://juejin.cn/post/7363452651797217306
评论
请登录