Webpack的业力:伊斯坦布尔的覆盖率是100%(0/0)

时间:2019-04-13 08:02:39

标签: angularjs webpack istanbul karma-coverage karma-webpack

我正在尝试使用Webpack(4.27.1)和Karma(3.1.3)+ Jasmine(jasmine-core 2.99.1)为Angular 1.6.6应用程序实现代码覆盖功能。所有测试均成功通过。但是,伊斯坦布尔(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):执行127之128(跳过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);

1 个答案:

答案 0 :(得分:1)

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

我们切换到istanbul-instrumenter-loader Webpack加载程序
以下配置将为我们生成代码覆盖范围
找不到我们遵循的原始指南,但是我将描述我们的配置为最佳 尽我所能:

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子文件夹中

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

karma / 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,
        }
    });

};

同样,因为业力配置位于子文件夹中,所以路径(基础,报告等)的配置不同。大多数配置不言自明。

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

karma / 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-事实证明这是一个巨大的挣扎,因为似乎未获取外部源地图且未映射源地图直到我们设置为inline配置。源映射不仅可以帮助覆盖代码,而且还可以在测试失败并打印出错误信息时提供帮助-它会引用原始代码行。
  • 最后,当进行覆盖时,将加载程序配置为排除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);

这与您的配置类似,但是由于我们有很多单独的模块,因此在每个测试中都导入了main中的angular和anglar-mocks