Tests: Switch to our own gulp-qunits module.

Since it handles PhantomJS as well as Node.js execution, and formats errors identically and quickly.
This commit is contained in:
Jürg Lehni 2016-01-28 14:39:40 +01:00
parent e02e9f4643
commit 567f286774
6 changed files with 35 additions and 111 deletions

View file

@ -2,6 +2,8 @@ Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
http://scratchdisk.com/ & http://jonathanpuckey.com/
All rights reserved.
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View file

@ -11,41 +11,32 @@
*/
var gulp = require('gulp'),
gulp_qunit = require('gulp-qunit'),
node_qunit = require('qunit'),
qunits = require('gulp-qunits'),
gutil = require('gulp-util');
gulp.task('test', ['test:browser', 'test:node']);
gulp.task('test:browser', ['minify:acorn'], function() {
return gulp.src('test/index.html')
.pipe(gulp_qunit({ timeout: 20, noGlobals: true }));
return gulp.src('index.html', { cwd: 'test' })
.pipe(qunits({
noGlobals: true,
timeout: 20
}));
});
gulp.task('test:node', ['minify:acorn'], function(callback) {
// Use the correct working directory for tests:
process.chdir('./test');
// Deactivate all logging since we're doing our own directly to gutil.log()
// from helpers.js
node_qunit.setup({ log: {} });
node_qunit.run({
maxBlockDuration: 100 * 1000,
deps: [
// To dynamically load the tests files from the sources, we need to
// require Prepro.js first. Since we need a sub-module, we have to
// use relative addresses: require('prepro/lib/node') does not work
// because of the way node-qunit handles relative addresses.
'../node_modules/prepro/lib/node.js',
// Note that loading dist/paper-full.js also works in combination
// with `gulp load`, in which case Prepro.js is present and handles
// the loading transparently.
{ path: '../dist/paper-full.js', namespace: 'paper' }
],
// Now load the actual test files through test/load.js, using Prepro.js
// for the loading, which was requested above.
code: 'load.js'
}, function(err, stats) {
err = err || stats.failed > 0 && 'QUnit assertions failed';
callback(err && new gutil.PluginError('node-qunit', err));
});
return gulp.src('load.js', { cwd: 'test' })
.pipe(qunits({
require: [
// To dynamically load the tests files from the sources, we need
// to require Prepro.js first.
'prepro/lib/node.js',
// Note that loading dist/paper-full.js also works in
// combination with `gulp load`, in which case Prepro.js is
// present and handles the loading transparently.
{ path: '../dist/paper-full.js', namespace: 'paper' }
],
noGlobals: true,
timeout: 20
}));
});

View file

@ -18,8 +18,10 @@ gulp.on('error', function(err) {
var msg = err.toString();
if (msg === '[object Object]')
msg = err;
gutil.log(ERROR, msg);
if (err.stack)
gutil.log(ERROR, err.stack);
msg += err.stack;
msg.split(/\r\n|\n|\r/mg).forEach(function(line) {
gutil.log(ERROR, line);
});
this.emit('end');
});

View file

@ -25,7 +25,7 @@
"README.md"
],
"engines": {
"node": ">=0.8.0 <6.0.0"
"node": ">=0.10.0 <6.0.0"
},
"dependencies": {
"jsdom": "git://github.com/lehni/jsdom.git#3d55789d0f4d55392721b1e22890837fde472375",
@ -43,7 +43,7 @@
"gulp-cached": "^1.1.0",
"gulp-jshint": "^2.0.0",
"gulp-prepro": "^2.2.0",
"gulp-qunit": "git://github.com/lehni/gulp-qunit.git#459c5603ceac460327a40dc89df6f19c786dc61b",
"gulp-qunits": "^1.5.1",
"gulp-rename": "^1.2.2",
"gulp-rimraf": "^0.2.0",
"gulp-shell": "^0.5.1",
@ -57,7 +57,6 @@
"jshint-summary": "^0.4.0",
"merge-stream": "^1.0.0",
"prepro": "^2.2.0",
"qunit": "^0.7.7",
"qunitjs": "^1.20.0",
"require-dir": "^0.3.0",
"resemblejs": "^2.1.0",

View file

@ -17,50 +17,6 @@ if (isNode) {
root = global;
// Resemble.js needs the Image constructor global.
global.Image = paper.window.Image;
// Handle logging to gulp directly from here, imitating the way gulp-qunit
// logs and formats results and errors:
var gutil = require('gulp-util'),
colors = gutil.colors,
done = false;
QUnit.log(function(details) {
if (!details.result) {
var lines = [
colors.red('Test failed') + ': ' + details.module + ': '
+ details.name
];
var line = 'Failed assertion: ' + (details.message || '');
if (details.expected !== undefined) {
line += ', expected: ' + details.expected + ', but was: '
+ details.actual;
}
lines.push(line);
if (details.source) {
lines = lines.concat(details.source.split(/\r\n|\n|\r/mg));
}
lines.forEach(function(line) {
gutil.log(line);
});
} else if (false) {
gutil.log(colors.green('Test succeeded') + ': ' + details.module
+ ': ' + details.name +': ' + (details.message || ''));
}
});
QUnit.done(function(details) {
if (done)
return;
var color = colors[details.failed > 0 ? 'red' : 'green'];
gutil.log('Took ' + details.runtime + 'ms to run '
+ colors.blue(details.total) + ' tests. ' + color(details.passed
+ ' passed, ' + details.failed + ' failed.'));
if (details.failed > 0) {
gutil.log('node-qunit: ' + gutil.colors.red('✖')
+ ' QUnit assertions failed');
} else {
gutil.log('node-qunit: ' + gutil.colors.green('✔')
+ ' QUnit assertions all passed');
}
done = true;
});
} else {
root = window;
// This is only required when running in the browser:
@ -93,37 +49,19 @@ QUnit.done(function(details) {
console.error = errorHandler;
});
var currentProject,
// In case we're stuck with an old QUnit, use a fake assert object with just
// the functions that we need:
// For now, a async() function returning a done() function:
fakeAssert = {
async: function() {
return function() {
QUnit.start();
};
}
};
var currentProject;
// NOTE: In order to "export" all methods into the shared Prepro.js scope when
// using node-qunit, we need to define global functions as:
// `var name = function() {}`. `function name() {}` does not work!
var test = function(testName, expected) {
// If this is running on an older version of QUnit (e.g. node-qunit is stuck
// with v1.10 for now), emulate the new assert.async() syntax through
// QUnit.asyncTest() and QUnit.start();
var emulate = !QUnit.async && 'assert' ===
// Get the parameter list from the passed function to see if we're
// expecting the assert object to do async...
expected.toString().match(/^\s*function[^\(]*\(([^\)]*)/)[1];
return QUnit[emulate ? 'asyncTest' : 'test'](testName, function(assert) {
return QUnit.test(testName, function(assert) {
// Since tests can be asynchronous, remove the old project before
// running the next test.
if (currentProject)
currentProject.remove();
currentProject = new Project();
expected(emulate ? fakeAssert : assert);
expected(assert);
});
};

View file

@ -23,7 +23,7 @@ test('Create a raster without a source and set its size', function() {
equals(raster.size, new Size(640, 480), true);
});
test('Create a raster from a url', function(assert) {
test('Create a raster from a URL', function(assert) {
var done = assert.async();
var raster = new Raster('assets/paper-js.gif');
raster.onLoad = function() {
@ -31,12 +31,12 @@ test('Create a raster from a url', function(assert) {
done();
};
raster.onError = function(event) {
pushFailure(event.event);
pushFailure('Loading from a valid local URL should not give an error.');
done();
};
});
test('Create a raster from a data url', function(assert) {
test('Create a raster from a data URL', function(assert) {
var done = assert.async();
var raster = new Raster('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABlJREFUeNpi+s/AwPCfgYmR4f9/hv8AAQYAHiAFAS8Lwy8AAAAASUVORK5CYII=');
raster.onLoad = function() {
@ -44,7 +44,7 @@ test('Create a raster from a data url', function(assert) {
done();
};
raster.onError = function(event) {
pushFailure(event.event);
pushFailure('Loading from a valid data URL should not give an error.');
done();
};
});
@ -101,10 +101,6 @@ test('Raster#getPixel / setPixel', function(assert) {
equals(raster.getPixel([0, 0]), color, 'alpha', { tolerance: 1e-2 });
done();
};
raster.onError = function(event) {
pushFailure(event.event);
done();
};
});
test('Raster#getSubCanvas', function(assert) {
@ -133,10 +129,6 @@ test('Raster#getSubCanvas', function(assert) {
}, true);
done();
};
raster.onError = function(event) {
pushFailure(event.event);
done();
};
});
test('Raster#getAverageColor(path)', function() {