I created an Aurelia app using the Aurelia CLI ( au new
) and would like to set up code coverage (preferably with karma-coverage , but if that's not possible I'll use whatever).
I first npm install karma-coverage --save-dev
then copy the test.js
task over to a cover.js
(so that I can run au cover
).
import {Server as Karma} from 'karma';
import {CLIOptions} from 'aurelia-cli';
// import project from "../aurelia.json";
export function cover(done) {
new Karma({
// This is the same as what's in karma.conf.js after running
// Except I added the 'src\\**\\*.js' part
files: [
'scripts\\vendor-bundle.js',
{pattern: 'test\\unit\\**\\*.js', included: false},
'test/aurelia-karma.js',
'scripts\\app-bundle.js',
'scripts\\materialize-bundle.js',
{pattern: 'src\\**\\*.js', included: false}
],
configFile: __dirname + '/../../karma.conf.js',
singleRun: !CLIOptions.hasFlag('watch'),
reporters: ['progress', 'coverage'],
//logLevel: 'debug',
preprocessors: {
// [project.unitTestRunner.source]: [project.transpiler.id], // Is this actually needed? Nothing changes if I add or remove this...
'src/**/*.js': ['babel', 'coverage']
},
coverageReporter: {
includeAllSources: true,
reporters: [
{type: 'html', dir: 'coverage'},
{type: 'text'}
]
}
}, done).start();
}
export default cover;
This... gets me somewhere?
But I don't think the tests are being linked to the individual src files (they're instead being linked to app-bundle.js
).
Is there any way to get code coverage at the src file level (ie not bundle level) for an Aurelia app?
export class App {
constructor() {
this.message = 'Hello World!';
}
}
"use strict";
const path = require('path');
const project = require('./aurelia_project/aurelia.json');
let testSrc = [
{ pattern: project.unitTestRunner.source, included: false },
'test/aurelia-karma.js'
];
let output = project.platform.output;
let appSrc = project.build.bundles.map(x => path.join(output, x.name));
let entryIndex = appSrc.indexOf(path.join(output, project.build.loader.configTarget));
let entryBundle = appSrc.splice(entryIndex, 1)[0];
let files = [entryBundle].concat(testSrc).concat(appSrc); console.log(files);
module.exports = function(config) {
config.set({
basePath: '',
frameworks: [project.testFramework.id],
files: files,
exclude: [],
preprocessors: {
[project.unitTestRunner.source]: [project.transpiler.id]
},
'babelPreprocessor': { options: project.transpiler.options },
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
// client.args must be a array of string.
// Leave 'aurelia-root', project.paths.root in this order so we can find
// the root of the aurelia project.
client: {
args: ['aurelia-root', project.paths.root]
}
});
};
From your terminal screenshot, it looks like you're getting coverage on your individual files src/app.js
(12.5%), src/environment.js
(0%) and src/main.js
(12.5%) in addition to the bundle file. It has to do with that extra line you added including the files that are in src/
.
I suspect that if you go to your coverage directory and view that in the browser, you'll see more detailed results.
I'm not sure about the Aurelia app specifically, but to get individual file coverage, you want to have your tests run against your original files instead of the bundled version and you want that same path to your original files to also be in preprocessors.
files: [
...
'src/**/*.js',
'path/to/tests/*.spec.js'
...
],
preprocessors: {
'src/**/*.js': ['coverage']
}
This pattern (which you've done) is what tells Karma to load the individual files, and include them in the coverage. At this point, I wouldn't bother loading the bundled application code since you have all the raw stuff being loaded.
Also be sure to load them in the order they're probably bundled in so that you can be sure Karma can initialize the app in the first place.
files: [
'src/app.js',
'src/environment.js',
'src/main.js'
]
And if you are putting your specs named myTest.spec.js
next to the files they test, you can use src/!(*.spec).js
to make sure that you are including application code without the tests.
I finally got it working, but it required a lot of under-the-hood modifications =\\
First I had to install the following packages
npm install karma-coverage --save-dev
npm install karma-requirejs --save-dev
npm install babel-plugin-istanbul --save-dev
This is based on test.js
.
requirejs
to the list of frameworks
(from the karma-requirejs package) included: false
) as well as test/aurelia-karma-cover.js
, which does the actual require
ing of test files. aurelia-karma.js
into aurelia-karma-cover.js
to not include /test/unit/setup.js
(it was giving me trouble with aurelia-browser-pal dependencies) "coverage"
from src file preprocessing ( babel-plugin-istanbul will now handle instrumentation of code - see statement at the end for details). import {Server as Karma} from 'karma';
import {CLIOptions} from 'aurelia-cli';
import project from "../aurelia.json";
export function cover(done) {
new Karma({
configFile: __dirname + '/../../karma.conf.js',
frameworks: [project.testFramework.id, 'requirejs'],
files: [
{pattern: 'src\\**\\*.js', included: false},
{pattern: 'test\\unit\\**\\*.js', included: false},
// This file actually loads the spec files via require - it's based on aurelia-karma.js
// but removes setup.js and its dependencies
'test/aurelia-karma-cover.js'
],
exclude: [
'src/environment.js',
'src/main.js',
'src/resources/index.js'
],
preprocessors: {
'src/**/*.js': ['babel'],
},
reporters: ['progress', 'coverage'],
singleRun: !CLIOptions.hasFlag('watch'),
coverageReporter: {
includeAllSources: true,
reporters: [
{type: 'html', dir: 'coverage'},
{type: 'text'}
]
}
}, done).start();
}
export default cover;
Just change var allTestFiles = ['/base/test/unit/setup.js'];
to var allTestFiles = [];
to avoid aurelia-pal-browser dependency errors.
Add "istanbul"
to the transpiler.options.plugins
list if using babel-plugin-istanbul .
* Without babel-plugin-istanbul
, code coverage works on post-transpiled code, which adds boilerplate that can't really be tested. This allows you to get to 100% code coverage ;)
@lebolo These were the adjustments I had to make to get things working here:
aurelia_project/tasks/cover.js
Included a constant to vendors path in the beginning of cover function:
const VENDORS_PATH = __dirname + '/../../node_modules/';
Used VENDORS_PATH to include libs I depend on, in files:
files: [
{pattern: VENDORS_PATH + 'moment/min/moment.min.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/unit/**/*.js', included: false},
'test/aurelia-karma-cover.js'
]
Included test files in preprocessors:
preprocessors: {
'src/**/*.js': ['babel'],
'test/unit/**/*.js': ['babel']
}
test/unit/aurelia-karma-cover.js
Change the way url is built in requirejs.load
function:
url = '/base/' + url;
=> url = ['/base', root, url].join('/');
Included one more function to config requirejs paths and calling it after patchRequireJS()
call:
function configRequire() {
var VENDORS_PATH = '../node_modules/';
requirejs.config({
paths: {
'moment': VENDORS_PATH + 'moment/min/moment.min'
}
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.