使用 Webpack 的 Karma:伊斯坦布尔覆盖率为 100%(0/0)

Posted

技术标签:

【中文标题】使用 Webpack 的 Karma:伊斯坦布尔覆盖率为 100%(0/0)【英文标题】:Karma with Webpack: Istanbul coverage is 100%(0/0) 【发布时间】:2019-09-03 21:49:36 【问题描述】:

我正在尝试使用 Webpack (4.27.1) 和 Karma(3.1.3) + Jasmine(jasmine-core 2.99.1) 为 Angular 1.6.6 应用程序实现代码覆盖功能。所有测试都成功通过。然而,Istanbul(0.4.5) 代码覆盖率结果显示100%(0/0)

测试结果输出

===========覆盖总结============

声明:100% (0/0) 分支:100% (0/0) 功能 : 100% ( 0/0 ) 行数:100% (0/0)

=========================================

HeadlessChrome 73.0.3683 (Windows 7.0.0):执行 128 次中的 127 次(跳过 1 次)成功(15.837 秒 / 14.88 秒) 总计:127 次成功

karma.config.js

const webpackConfig = require('./webpack.config.js');
webpackConfig.devtool = false;
module.exports = function (config) 
  config.set(
      plugins: [
          'karma-*'
      ],
      singleRun: true,
      frameworks: ['jasmine'],
      basePath: '../',
      exclude: [],
      browsers: ['ChromeHeadless'],
      preprocessors: 
          'test/unit/index_test.js': ['webpack'],
          'app/index.js': ['coverage']
      ,
      'reporters': [
          'coverage', 'spec', 'html', 'junit'
      ],
      webpack: webpackConfig,
      coverageReporter: 
          dir: 'target/test-results/coverage',
          reporters: [
               type: 'html', subdir: 'html' ,
               type: 'lcovonly', subdir: '.' ,
               type: 'text-summary' 
          ],
          instrumenterOptions: 
              istanbul:  noCompact: true 
          ,
          check: 
              global: 
                  statements: 90.0,
                  branches: 80.0,
                  functions: 80.0,
                  lines: 90.0
              
          
      ,
      reportSlowerThan: 100,
      browserNoActivityTimeout: 60000,
      autoWatch: true,
      files: [
          'node_modules/babel-polyfill/dist/polyfill.js',
          'test/unit/index_test.js',
      ]
  );
;

webpack.config.js

const webpack = require('webpack');
const path = require('path');
module.exports = merge.smart(base, 
    entry: 
        app: './src/app.js'
    ,
    output: 
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
    ,
    devtool: 'eval',
    devServer: open: true,
    module: 
        rules: [
            
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            ,
         ]
      
  )
;

.babelrc


  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "plugins": [
      "angularjs-annotate",
      "@babel/plugin-transform-modules-commonjs"
  ],
  "env": 
      "test": 
      "plugins": ["istanbul"]
    
  

index_test.js

 import 'core-js/es6/reflect';
 import 'core-js/client/shim';

 require('app/index');
 require('angular');
 require('angular-mocks/angular-mocks');

 beforeEach(() => 
     angular.mock.module('app');
 );

 const testContext = require.context('.', true, /\.spec.js?$/);
 testContext.keys().forEach(testContext);

 const srcContext = require.context('../../app/', false, /app\.module\.js$/);
 srcContext.keys().forEach(srcContext);

【问题讨论】:

这可能是您的 index_test.js 中的问题,使用 path.join(__dirname, '') 就像您在 webpack 配置中所做的那样,真的不确定但试一试。另一个想法将 testContext 中的正则表达式更改为 /\.spec\.js?$/ 你错过了一个反斜杠 【参考方案1】:

我们从未设法为我们的 angularjs 项目配置代码覆盖率 istanbul。这个版本的伊斯坦布尔也已被弃用

我们切换到istanbul-instrumenter-loader webpack loader 以下配置将为我们生成代码覆盖率 找不到我们遵循的原始指南,但我会尽可能地描述我们的配置 尽我所能:

package.json devDependencies(与代码覆盖率相关)


  "babel-loader": "^8.0.5",
  "istanbul-instrumenter-loader": "^3.0.1", // webpack loader added in coverage tests
  "jasmine-core": "^2.99.1",
  "karma": "^3.1.3",
  "karma-chrome-launcher": "^2.2.0",
  "karma-cli": "^1.0.1",
  "karma-coverage-istanbul-reporter": "^1.4.2", // coverage reporter used in tests
  "karma-html-reporter": "^0.2.7", // html reporter used in tests
  "karma-jasmine": "^1.1.1",
  "karma-ng-html2js-preprocessor": "^1.0.0",
  "karma-sourcemap-loader": "^0.3.7",
  "karma-spec-reporter": "0.0.32",
  "karma-webpack": "^3.0.5",
  "webpack": "4.28.4",

测试包版本和你的很接近

package.json 测试脚本:

我们的 karma 配置位于 ./karma 子文件夹中

"scripts": 
  "test": "NODE_ENV=development karma start karma/karma.conf.js",
  "cover": "npm test -- --cover --reportHtml", // pass flags to karma.conf

业力/karma.conf.js

const path = require('path');
const makeWebpackTestConfig = require('./karma.webpack.config');

module.exports = (config) => 

    const REPORTS_PATH = path.join(__dirname, '../reports/');
    const cover = config.cover || process.env.COVER;
    const webstorm = process.env.WEBSTORM; // Running coverage from inside the IDE 
    const webpack = makeWebpackTestConfig(cover);

    const reporters = config.reportHtml ? ['html'] : [];

    if (!webstorm) reporters.push('spec');
    if (cover) reporters.push('coverage-istanbul');

    config.set(

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '../',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],

        // list of files / patterns to load in the browser
        files: ['src/main.tests.js'],

        // list of files to exclude
        exclude: [],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: 
            'src/**/*.js': ['webpack', 'sourcemap'],
            'src/**/*.html': ['webpack'],
            'src/**/*.less': ['webpack'],
        ,

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters,

        specReporter: 
            maxLogLines: 5,             // limit number of lines logged per test
            suppressErrorSummary: false,// do not print error summary
            suppressFailed: false,      // do not print information about failed tests
            suppressPassed: false,      // do not print information about passed tests
            suppressSkipped: true,      // do not print information about skipped tests
            showSpecTiming: true,       // print the time elapsed for each spec
            failFast: false              // test would finish with error when a first fail occurs.
        ,

        htmlReporter: 
            outputDir: path.join(REPORTS_PATH, 'unit-tests'), // where to put the reports
            // templatePath: null, // set if you moved jasmine_template.html
            focusOnFailures: true, // reports show failures on start
            namedFiles: true, // name files instead of creating sub-directories
            pageTitle: 'Unit Tests', // page title for reports; browser info by default
            urlFriendlyName: true, // simply replaces spaces with _ for files/dirs
            reportName: 'index', // report summary filename; browser info by default

            // experimental
            preserveDescribeNesting: true, // folded suites stay folded
            foldAll: true, // reports start folded (only with preserveDescribeNesting)
        ,

        coverageIstanbulReporter: 
            reports: ['lcov', 'text-summary'],
            dir: webstorm ? undefined : path.join(REPORTS_PATH, 'code-coverage'),
        ,

        // web server port
        port: 9876,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN ||
        // config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: false,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['RunnerHeadless'],

        customLaunchers: 
            RunnerHeadless: 
                base: 'ChromeHeadless',
                flags: ['--headless', '--no-sandbox', '--disable-gpu', '--disable-translate', '--disable-extensions'],
            ,
        ,

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true,

        webpack,

        webpackMiddleware: 
            stats: 'errors-only',
        ,

        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: Infinity,

        client: 
            // Log browser console only locally
            captureConsole: !!process.env.WEBSTORM,
        
    );

;

再次,因为 karma config 位于子文件夹中,路径(base、reports 等)的配置不同。大多数配置是不言自明的。

我们有一个环境变量WEBSTORM,我们在从IDE 内部运行覆盖时设置它。 还要记住,需要启用源映射才能正确映射到原始源行,因为原始源是由 babel 转换的。 我们正在使用自定义 browsers 配置,您的情况可能不需要此配置

业力/karma.webpack.config.js

const makeWebpackConfig = require('../webpack/base-config');

module.exports = (cover) => 

    const defaultConfig = makeWebpackConfig();

    // Remove entry. Karma will provide the source
    defaultConfig.entry = null;

    // Have source maps generated so covered statements are mapped correctly
    defaultConfig.devtool = 'inline-source-map';

    defaultConfig.mode = 'development';

    defaultConfig.optimization = 
        splitChunks: false,
        runtimeChunk: false,
        minimize: false,
    ;

    if (cover) 

        defaultConfig.module.rules.push(
            test: /\.js$/,
            use: 
                loader: 'istanbul-instrumenter-loader',
                options:  esModules: true ,
            ,
            enforce: 'post',
            exclude: /node_modules|\.spec\.js$/,
        );

    

    return defaultConfig;

;

makeWebpackConfig 创建我们在运行开发或生产构建时使用的基本配置,其中包含 babel-loader 和其他样式、html、文件等加载器...

karma.webpack.conf.js 中覆盖需要覆盖的任何设置 条目已删除,我想,无论如何,Karam 都会覆盖它。 重要 devtool 设置为 inline-source-map - 事实证明这是一场巨大的斗争,因为似乎外部源映射没有被拾取并且源映射在我们设置为 @987654335 之前不起作用@ 配置。源图不仅有助于代码覆盖,而且在测试失败和打印错误信息时也有帮助——它将引用原始代码行。 最后,在进行覆盖时,将加载程序配置为排除 node_modules 和任何外部源,同时排除测试本身

.babelrc 配置


  "presets": [
    ["@babel/preset-env",  "modules": "commonjs" ],
    "@babel/preset-react"
  ],
  "plugins": [
    "angularjs-annotate",
    ["@babel/plugin-proposal-decorators", 
      "legacy": true
    ],
    "@babel/plugin-syntax-dynamic-import",
    "@babel/plugin-syntax-import-meta",
    ["@babel/plugin-proposal-class-properties", 
      "loose": true
    ],
    "@babel/plugin-proposal-json-strings",
    "@babel/plugin-proposal-function-sent",
    "@babel/plugin-proposal-export-namespace-from",
    "@babel/plugin-proposal-numeric-separator",
    "@babel/plugin-proposal-throw-expressions",
    "@babel/plugin-proposal-export-default-from",
    "@babel/plugin-proposal-logical-assignment-operators",
    "@babel/plugin-proposal-optional-chaining",
    "@babel/plugin-proposal-nullish-coalescing-operator",
    "@babel/plugin-proposal-do-expressions",
    "@babel/plugin-proposal-function-bind"
  ]


应该可以使用您自己的 .babelrc 配置。 "modules": "commonjs" 出于某种原因对我们很重要,但现在不记得了

测试入口点 - src/main.tests.js

import '@babel/polyfill';
import './appConfig';
import './main';

const testsContext = require.context('.', true, /\.spec.js$/);
testsContext.keys().forEach(testsContext);

这与您的配置类似,尽管在 mainanglar-mocks 中导入了 angular,因为我们有很多单独的模块,所以每个测试都导入了 anglar-mocks

【讨论】:

以上是关于使用 Webpack 的 Karma:伊斯坦布尔覆盖率为 100%(0/0)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Istanbul + Webpack 覆盖 JSX 文件的代码

Karma Webpack 源图不起作用

Karma + Browserify + Jasmine + 伊斯坦布尔 + React 覆盖

Parse Karma-覆盖 |伊斯坦布尔报告

Karma-Coverage 和伊斯坦布尔 HTML 报告未输出到预期目录

在 Karma 中设置 NODE_ENV 以运行 webpack 的正确方法是啥?