在Next.js应用中使用Istanbul实现代码覆盖率遇阻求助
Next.js + Cypress 代码覆盖率配置失败解决方案
问题描述
我用Cypress给Next.js应用写了前端测试,现在要加代码覆盖率检测来追踪未测试模块,但按照官方指南用istanbuljs实现时一直失败。试过用nyc把代码插桩到/instrumented目录运行,也试过集成到Babel流水线,结果要么测试正常跑但没覆盖率数据,要么应用直接启动不了。如果项目里有.babelrc文件,每个页面/组件都会抛出'React is undefined'错误。
当前依赖配置:
"devDependencies": { "@babel/preset-react": "^7.18.6", "@cypress/code-coverage": "^3.10.0", "babel-plugin-istanbul": "^6.1.1", "babel-plugin-transform-class-properties": "^6.24.1", "cypress": "^10.1.0", "cypress-react-selector": "^2.3.20", "nyc": "^15.1.0" }
之前的错误配置:
- .babelrc(存在则应用崩溃):
{ "presets": ["@babel/preset-react"], "plugins": ["transform-class-properties", "istanbul"] }
- support/e2e.js:
import './commands'; import '@cypress/code-coverage/support';
- cypress.config.js:
const { defineConfig } = require('cypress'); module.exports = defineConfig({ e2e: { baseUrl: 'http://localhost:3000', setupNodeEvents(on, config) { require('@cypress/code-coverage/task')(on, config); on('file:preprocessor', require('@cypress/code-coverage/use-babelrc')); return config; }, }, watchForFileChanges: false, defaultCommandTimeout: 1000000, });
解决方案
1. 删除根目录的.babelrc文件
Next.js默认使用next/babel预设,这个预设包含了自动引入React的功能(无需手动写import React from 'react')。自定义.babelrc会覆盖Next.js的默认预设,导致React未被自动引入,出现'React is undefined'错误。
2. 在next.config.js中配置Babel插桩
把istanbul插件集成到Next.js的webpack配置里,仅在测试环境启用:
/** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, webpack: (config, { dev, isServer }) => { // 仅在测试环境添加istanbul插桩 if (process.env.NODE_ENV === 'test') { config.module.rules.push({ test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['next/babel'], // 复用Next.js默认Babel预设 plugins: ['babel-plugin-istanbul', 'transform-class-properties'], }, }, }); } return config; }, }; module.exports = nextConfig;
3. 调整Cypress配置文件
替换原有的file:preprocessor配置,改用Next.js的webpack配置作为预处理器,同时可以启用Cypress的devServer自动启动Next服务:
const { defineConfig } = require('cypress'); const { startDevServer } = require('@cypress/webpack-dev-server'); const nextConfig = require('./next.config.js'); module.exports = defineConfig({ e2e: { // 注释baseUrl,改用devServer自动启动服务 // baseUrl: 'http://localhost:3000', setupNodeEvents(on, config) { // 注册代码覆盖率任务 require('@cypress/code-coverage/task')(on, config); return config; }, // 配置devServer自动启动Next应用 devServer: { framework: 'next', bundler: 'webpack', webpackConfig: nextConfig, }, }, watchForFileChanges: false, defaultCommandTimeout: 1000000, });
4. 添加NYC配置(可选)
在项目根目录创建.nycrc文件,自定义覆盖率报告格式和范围:
{ "include": ["src/**/*.{js,jsx,ts,tsx}"], "exclude": ["node_modules", ".next", "cypress", "public"], "reporter": ["html", "text-summary"], "all": true }
5. 运行测试命令
在package.json中添加测试脚本,确保设置测试环境变量:
"scripts": { "test:e2e": "NODE_ENV=test cypress run", "test:e2e:open": "NODE_ENV=test cypress open" }
执行命令:
npm run test:e2e
测试完成后,会在项目根目录生成coverage文件夹,打开其中的index.html即可查看详细的代码覆盖率报告。
内容的提问来源于stack exchange,提问作者alon rubin
相关产品推荐
相关产品推荐

