2016-10-21 176 views
4

我正在关注设置Webpack Angular 2项目的this tutorial在Angular 2.1.0 Webpack上设置单元测试代码覆盖率

我可以用设置运行单元测试,但我已经尝试使用karma覆盖和remap-istanbul向项目添加代码覆盖率,但似乎karma覆盖不会输出coverage中的任何内容以.json。

我需要添加到karma配置才能使测试配置正常工作?

这里是我当前的配置:

var webpackConfig = require('./webpack.test'); 

module.exports = function (config) { 
    var _config = { 
     basePath: '', 

     frameworks: ['jasmine'], 

     files: [ 
      {pattern: './config/karma-test-shim.js', watched: false} 
     ], 

     preprocessors: { 
      './config/karma-test-shim.js': ['webpack', 'sourcemap'] 
     }, 

     webpack: webpackConfig, 

     webpackMiddleware: { 
      stats: 'errors-only' 
     }, 

     webpackServer: { 
      noInfo: true 
     }, 

     reporters: ['progress'], 
     port: 9876, 
     colors: true, 
     logLevel: config.LOG_INFO, 
     autoWatch: false, 
     browsers: ['PhantomJS'], 
     singleRun: true 
    }; 

    config.set(_config); 
}; 

回答

4

你有两个选择,最简单的方法是使用angular-cli。最困难的方法是基于该教程进行代码覆盖所需的更改,这是非常多的。你将被强迫的主要事情之一是转换到Webpack 2,我无法使用Webpack 1使awesome-typescript-loader与业力一起工作。代码覆盖率始终是空的。我得到了一些灵​​感来自于angular-cliangular2-webpack-starter这里的变化:

karma.conf.js:补充一点:

remapIstanbulReporter: { 
    reports: { 
    html: 'coverage', 
    lcovonly: './coverage/coverage.lcov' 
    } 
}, 

并改变这一点:

reporters: ['progress'],  

这样:

reporters: ['progress', 'karma-remap-istanbul'], 

有很多更改的WebPack的configs,所以我只是要粘贴整个配置文件,它更容易:

webpack.common.js

var webpack = require('webpack'); 
var HtmlWebpackPlugin = require('html-webpack-plugin'); 
var ExtractTextPlugin = require('extract-text-webpack-plugin'); 
var helpers = require('./helpers'); 

module.exports = { 
    entry: { 
    'polyfills': './src/polyfills.ts', 
    'vendor': './src/vendor.ts', 
    'app': './src/main.ts' 
    }, 

    resolve: { 
    extensions: ['.ts', '.js'] 
    }, 

    module: { 
    rules: [ 
     { 
     test: /\.ts$/, 
     loaders: ['awesome-typescript-loader', 'angular2-template-loader'], 
     exclude: [/\.(spec|e2e)\.ts$/] 
     }, 
     { 
     test: /\.html$/, 
     loader: 'html' 
     }, 
     { 
     test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, 
     loader: 'file?name=assets/[name].[hash].[ext]' 
     }, 
     { 
     test: /\.css$/, 
     exclude: helpers.root('src', 'app'), 
     loader: ExtractTextPlugin.extract({ 
      fallbackLoader: 'style-loader', 
      loader: 'css-loader' 
     }) 
     }, 
     { 
     test: /\.css$/, 
     include: helpers.root('src', 'app'), 
     loader: 'raw' 
     } 
    ] 
    }, 

    plugins: [ 
    new webpack.optimize.CommonsChunkPlugin({ 
     // Optimizing ensures loading order in index.html 
     name: ['polyfills', 'vendor', 'app'].reverse() 
    }), 
    new webpack.optimize.CommonsChunkPlugin({ 
     minChunks: Infinity, 
     name: 'inline', 
     filename: 'inline.js', 
     sourceMapFilename: 'inline.map' 
    }), 

    new HtmlWebpackPlugin({ 
     template: 'src/index.html' 
    }) 
    ] 
}; 

webpack.dev.js

var webpack = require('webpack'); 
var webpackMerge = require('webpack-merge'); 
var ExtractTextPlugin = require('extract-text-webpack-plugin'); 
var commonConfig = require('./webpack.common.js'); 
var helpers = require('./helpers'); 

module.exports = webpackMerge(commonConfig, { 
    devtool: 'cheap-module-eval-source-map', 

    output: { 
    path: helpers.root('dist'), 
    filename: '[name].js', 
    chunkFilename: '[id].chunk.js', 
    sourceMapFilename: '[name].map', 
    library: 'ac_[name]', 
    libraryTarget: 'var' 
    }, 

    plugins: [ 
    new webpack.LoaderOptionsPlugin({ 
     options: { 
     tslint: { 
      emitErrors: false, 
      failOnHint: false, 
      resourcePath: 'src' 
     }, 
     } 
    }), 
    new ExtractTextPlugin('[name].css') 
    ], 

    devServer: { 
    historyApiFallback: true, 
    stats: 'minimal', 
    watchOptions: { 
     aggregateTimeout: 300, 
     poll: 1000 
    }, 
    outputPath: helpers.root('dist') 
    }, 
    node: { 
    global: true, 
    crypto: 'empty', 
    process: true, 
    module: false, 
    clearImmediate: false, 
    setImmediate: false 
    } 
}); 

webpack.prod.js

var webpack = require('webpack'); 
var webpackMerge = require('webpack-merge'); 
var WebpackMd5Hash = require('webpack-md5-hash'); 
var ExtractTextPlugin = require('extract-text-webpack-plugin'); 
var commonConfig = require('./webpack.common.js'); 
var helpers = require('./helpers'); 

const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; 

module.exports = webpackMerge(commonConfig, { 
    devtool: 'source-map', 

    output: { 
    path: helpers.root('dist'), 
    filename: '[name].[chunkhash].js', 
    sourceMapFilename: '[name].[chunkhash].bundle.map', 
    chunkFilename: '[id].[chunkhash].chunk.js' 
    }, 

    plugins: [ 
    new WebpackMd5Hash(), 
    new webpack.NoErrorsPlugin(), 
    new webpack.optimize.UglifyJsPlugin({ 
     mangle: { screw_ie8: true }, 
     compress: { screw_ie8: true } 
    }), 
    new ExtractTextPlugin('[name].[hash].css'), 
    new webpack.DefinePlugin({ 
     'process.env': { 
     'ENV': JSON.stringify(ENV) 
     } 
    }), 
    new webpack.LoaderOptionsPlugin({ 
     options: { 
     tslint: { 
      emitErrors: true, 
      failOnHint: true, 
      resourcePath: helpers.root('src') 
     }, 
     htmlLoader: { 
      minimize: true, 
      removeAttributeQuotes: false, 
      caseSensitive: true, 
      customAttrSurround: [ 
      [/#/, /(?:)/], 
      [/\*/, /(?:)/], 
      [/\[?\(?/, /(?:)/] 
      ], 
      customAttrAssign: [/\)?\]?=/] 
     } 
     } 
    }), 
    new webpack.ContextReplacementPlugin(
     /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/, 
     helpers.root('src') 
    ) 
    ], 
    node: { 
    fs: 'empty', 
    global: true, 
    crypto: 'empty', 
    process: true, 
    module: false, 
    clearImmediate: false, 
    setImmediate: false 
    } 
}); 

webpack.test.js

var helpers = require('./helpers'); 
var path = require('path'); 
var atl = require('awesome-typescript-loader'); 
var webpack = require('webpack'); 

module.exports = { 
    devtool: 'inline-source-map', 
    context: path.resolve(__dirname, './'), 
    resolve: { 
    extensions: ['.ts', '.js'], 
    plugins: [ 
     new atl.TsConfigPathsPlugin({ 
     tsconfig: helpers.root('tsconfig.json') 
     }) 
    ] 
    }, 
    entry: { 
    test: helpers.root('config/karma-test-shim') 
    }, 
    output: { 
    path: './dist.test', 
    filename: '[name].bundle.js' 
    }, 
    module: { 
    rules: [ 
     { 
     test: /\.ts$/, 
     enforce: 'pre', 
     loader: 'tslint-loader', 
     exclude: [ 
      helpers.root('node_modules') 
     ] 
     }, 
     { 
     test: /\.js$/, 
     enforce: 'pre', 
     loader: 'source-map-loader', 
     exclude: [ 
      helpers.root('node_modules/rxjs'), 
      helpers.root('node_modules/@angular') 
     ] 
     }, 
     { 
     test: /\.ts$/, 
     loaders: [ 
      { 
      loader: 'awesome-typescript-loader', 
      query: { 
       tsconfig: helpers.root('tsconfig.json'), 
       module: 'commonjs', 
       target: 'es5', 
       useForkChecker: true 
      } 
      }, 
      { 
      loader: 'angular2-template-loader' 
      } 
     ], 
     exclude: [/\.e2e\.ts$/] 
     }, 
     { 
     test: /\.html$/, 
     loader: 'html' 

     }, 
     { 
     test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, 
     loader: 'null' 
     }, 
     { 
     test: /\.css$/, 
     exclude: helpers.root('src', 'app'), 
     loader: 'null' 
     }, 
     { 
     test: /\.css$/, 
     include: helpers.root('src', 'app'), 
     loader: 'raw' 
     }, 
     { 
     test: /\.(js|ts)$/, loader: 'sourcemap-istanbul-instrumenter-loader', 
     enforce: 'post', 
     exclude: [ 
      /\.(e2e|spec)\.ts$/, 
      /node_modules/ 
     ], 
     query: { 'force-sourcemap': true } 
     }, 
    ] 
    }, 
    plugins: [ 
    new webpack.SourceMapDevToolPlugin({ 
     filename: null, // if no value is provided the sourcemap is inlined 
     test: /\.(ts|js)($|\?)/i // process .js and .ts files only 
    }), 
    new webpack.LoaderOptionsPlugin({ 
     options: { 
     tslint: { 
      emitErrors: false, 
      failOnHint: false, 
      resourcePath: `./src` 
     } 
     } 
    }), 
    new webpack.ContextReplacementPlugin(
     /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/, 
     helpers.root('src') 
    ) 
    ], 
    node: { 
    fs: 'empty', 
    global: true, 
    process: false, 
    crypto: 'empty', 
    module: false, 
    clearImmediate: false, 
    setImmediate: false 
    } 
} 

的package.json
您需要安装新的包和更新您的启动脚本,以这样的:

"start": "webpack-dev-server --config config/webpack.dev.js --profile --watch --content-base src/", 

而且安装这些软件包:

npm i -D [email protected] karma-remap-istanbul source-map-loader sourcemap-istanbul-instrumenter-loader tslint tslint-loader [email protected] [email protected] webpack-md5-hash 

最后但并非我们只需要至少做对tsconfig.json一些变化,自我们现在用tslint我们添加一个tslint.json文件。

tsconfig.json

{ 
    "compilerOptions": { 
    "buildOnSave": false, 
    "compileOnSave": false, 
    "emitDecoratorMetadata": true, 
    "experimentalDecorators": true, 
    "module": "commonjs", 
    "moduleResolution": "node", 
    "outDir": "dist/out-tsc", 
    "noImplicitAny": true, 
    "removeComments": false, 
    "sourceMap": true, 
    "suppressImplicitAnyIndexErrors": true, 
    "target": "es5" 
    } 
} 

tslint.json:

{ 
    "rules": { 
    "member-access": false, 
    "member-ordering": [ 
     true, 
     "public-before-private", 
     "static-before-instance", 
     "variables-before-functions" 
    ], 
    "no-any": false, 
    "no-inferrable-types": false, 
    "no-internal-module": true, 
    "no-var-requires": false, 
    "typedef": false, 
    "typedef-whitespace": [ 
     true, 
     { 
     "call-signature": "nospace", 
     "index-signature": "nospace", 
     "parameter": "nospace", 
     "property-declaration": "nospace", 
     "variable-declaration": "nospace" 
     }, 
     { 
     "call-signature": "space", 
     "index-signature": "space", 
     "parameter": "space", 
     "property-declaration": "space", 
     "variable-declaration": "space" 
     } 
    ], 

    "ban": false, 
    "curly": false, 
    "forin": true, 
    "label-position": true, 
    "label-undefined": true, 
    "no-arg": true, 
    "no-bitwise": true, 
    "no-conditional-assignment": true, 
    "no-console": [ 
     true, 
     "debug", 
     "info", 
     "time", 
     "timeEnd", 
     "trace" 
    ], 
    "no-construct": true, 
    "no-debugger": true, 
    "no-duplicate-variable": true, 
    "no-empty": false, 
    "no-eval": true, 
    "no-null-keyword": false, 
    "no-shadowed-variable": true, 
    "no-string-literal": false, 
    "no-switch-case-fall-through": true, 
    "no-unreachable": true, 
    "no-unused-expression": true, 
    "no-unused-variable": false, 
    "no-use-before-declare": true, 
    "no-var-keyword": true, 
    "radix": true, 
    "switch-default": true, 
    "triple-equals": [ 
     true, 
     "allow-null-check" 
    ], 
    "use-strict": [ 
     true, 
     "check-module" 
    ], 

    "eofline": true, 
    "indent": [ 
     true, 
     "spaces" 
    ], 
    "max-line-length": [ 
     true, 
     100 
    ], 
    "no-require-imports": false, 
    "no-trailing-whitespace": true, 
    "object-literal-sort-keys": false, 
    "trailing-comma": [ 
     true, 
     { 
     "multiline": false, 
     "singleline": "never" 
     } 
    ], 

    "align": false, 
    "class-name": true, 
    "comment-format": [ 
     true, 
     "check-space" 
    ], 
    "interface-name": false, 
    "jsdoc-format": true, 
    "no-consecutive-blank-lines": false, 
    "no-constructor-vars": false, 
    "one-line": [ 
     true, 
     "check-open-brace", 
     "check-catch", 
     "check-else", 
     "check-finally", 
     "check-whitespace" 
    ], 
    "quotemark": [ 
     true, 
     "single", 
     "avoid-escape" 
    ], 
    "semicolon": [true, "always"], 
    "variable-name": [ 
     true, 
     "check-format", 
     "allow-leading-underscore", 
     "ban-keywords" 
    ], 
    "whitespace": [ 
     true, 
     "check-branch", 
     "check-decl", 
     "check-operator", 
     "check-separator", 
     "check-type" 
    ] 
    } 
} 

如果你愿意,你可以检查Angular.io设置之间的差异(左)和我所做的改变,使覆盖工作(右)here

+0

工程!它不包括未包含在测试中的文件的覆盖范围,但显示任何包含测试的文件的覆盖率。我必须使用教程中的原始tsconfig.json,而不是这里显示的那个。 –

相关问题