Карма с Webpack: охват Стамбула составляет 100% (0/0) - PullRequest
1 голос
/ 13 апреля 2019

Я пытаюсь реализовать функциональность покрытия кода для приложения Angular 1.6.6 с Webpack (4.27.1) и Karma (3.1.3) + Jasmine (jasmine-core 2.99.1).Все тесты успешно пройдены.Однако результат покрытия кода в Стамбуле (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 Ответ

1 голос
/ 14 апреля 2019

Нам никогда не удавалось настроить покрытие кода с помощью istanbul для нашего проекта angularjs. Также эта версия Стамбула устарела

Мы перешли на 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

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

};

Опять же, поскольку конфигурация кармы находится в подпапках, пути (база, отчеты и т. Д.) Настраиваются по-разному. Большая часть конфигурации говорит сама за себя.

  • У нас есть переменная env 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 создает базовую конфигурацию, которую мы используем при запуске dev или производственных сборок, которые имеют babel-loader и другие загрузчики для стилей, html, файлов и т. Д. *

  • Какая бы настройка ни была необходима, переопределение в karma.webpack.conf.js
  • Запись удалена, я думаю, Карам все равно перезапишет ее.
  • Важно devtool установлено на inline-source-map - это оказалось огромной борьбой, так как кажется, что карты внешнего источника не подобраны, и отображение источника не сработало, пока мы не установили inline конфигурация. Исходные карты помогают не только с охватом кода, но также и когда тесты не выполняются и информация об ошибках выводится на печать - она ​​ссылается на исходные строки кода.
  • И, наконец, при выполнении покрытия настройте загрузчик, чтобы исключить node_modules и любые внешние источники, а также исключить сами тесты

.babelrc config

{
  "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);

Это похоже на вашу конфигурацию, хотя angular импортируется в main и anglar-mocks импортируются для каждого теста, так как у нас много отдельных модулей

...