Skip to content

Commit

Permalink
grunt and shell script for tests and compare
Browse files Browse the repository at this point in the history
  • Loading branch information
timdream committed Apr 15, 2014
1 parent 516a345 commit 335cf10
Show file tree
Hide file tree
Showing 7 changed files with 300 additions and 8 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules
/slimerjs.log
/profile
65 changes: 65 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

module.exports = function(grunt) {

var HTTPD_PORT = 28080 + Math.floor(Math.random() * 10);
var TEST_URL = 'http://localhost:' + HTTPD_PORT + '/test/';

var BASE_COMMIT = grunt.option('base-commit') || '';

grunt.initConfig({
shell: {
'qunit-slimerjs': {
command: './test/run-slimerjs.sh ' + TEST_URL + '?allownoref=true',
options: {
stdout: true,
stderr: true,
failOnError: true,
execOptions: {
maxBuffer: Infinity
}
}
},
'compare-slimerjs': {
command: './test/run-slimerjs-compare.sh ' +
TEST_URL + ' ' + BASE_COMMIT,
options: {
stdout: true,
stderr: true,
failOnError: true,
execOptions: {
maxBuffer: Infinity
}
}
}
},
connect: {
test: {
options: {
port: HTTPD_PORT
}
}
},
jshint: {
options: {
jshintrc: true
},
all: ['src/*.js']
}
});

grunt.loadNpmTasks('grunt-contrib-jshint');

grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-connect');

grunt.registerTask('test', ['test-slimerjs']);
grunt.registerTask('compare', ['compare-slimerjs']);

// Run the test suite with QUnit on SlimerJS
grunt.registerTask('test-slimerjs', ['connect', 'shell:qunit-slimerjs']);

// Run the test suite with QUnit on SlimerJS
grunt.registerTask('compare-slimerjs',
['connect', 'shell:compare-slimerjs']);
};
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@ With the information, wordcloud.js will then try to find a place to fit the word

## Testing

Semi-automatic tests are available with [QUnit](http://qunitjs.com/).

Unfortunately, even with all the randomness options disabled,
the output will still depend on the browser and the font rendering of the OS
(and ClearType settings!). Hence, I cannot supply a set of reference images.
The tests won't pass unless you manually confirm them in your environment first --
subsequent tests are considered passed if the reference image exists
(saved when you confirm the output) and the output is identical to it pixel-by-pixel.
Tests are available with [QUnit](http://qunitjs.com/) and `grunt`.
To setup environment for testing, run `npm install` and manually install [SlimerJS](http://slimerjs.org/) of your platform.

Use `grunt test` to ensure all options can be set without JavaScript error.
Use `grunt compare --base-commit=master` to compare your proposed fix with `master` branch.
16 changes: 16 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "wordcloud2.js",
"repository": {
"type": "git",
"url": "https://github.com/timdream/wordcloud2.js"
},
"scripts": {
"test": "grunt test"
},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-shell": "~0.6.4",
"grunt-contrib-connect": "~0.7.1",
"grunt-contrib-jshint": "~0.10.0"
}
}
134 changes: 134 additions & 0 deletions test/headless-runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Simply ripped from
* https://github.com/jquery/qunit/blob/master/addons/phantomjs/runner.js
*/
/*global phantom:false, require:false, console:false, window:false, QUnit:false */

(function() {
'use strict';

var url, page, timeout,
args = require('system').args;

// arg[0]: scriptName, args[1...]: arguments
if (args.length < 2 || args.length > 3) {
console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite] [timeout-in-seconds]');
phantom.exit(1);
}

url = args[1];
page = require('webpage').create();
if (args[2] !== undefined) {
timeout = parseInt(args[2], 10);
}

// Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
page.onConsoleMessage = function(msg) {
console.log(msg);
};

page.onInitialized = function() {
page.evaluate(addLogging);
};

page.onCallback = function(message) {
var result,
failed;

if (message) {
if (message.name === 'QUnit.done') {
result = message.data;
failed = !result || !result.total || result.failed;

if (!result.total) {
console.error('No tests were executed. Are you loading tests asynchronously?');
}

phantom.exit(failed ? 1 : 0);
}
}
};

page.open(url, function(status) {
if (status !== 'success') {
console.error('Unable to access network: ' + status);
phantom.exit(1);
} else {
// Cannot do this verification with the 'DOMContentLoaded' handler because it
// will be too late to attach it if a page does not have any script tags.
var qunitMissing = page.evaluate(function() { return (typeof QUnit === 'undefined' || !QUnit); });
if (qunitMissing) {
console.error('The `QUnit` object is not present on this page.');
phantom.exit(1);
}

// Set a timeout on the test running, otherwise tests with async problems will hang forever
if (typeof timeout === 'number') {
setTimeout(function() {
console.error('The specified timeout of ' + timeout + ' seconds has expired. Aborting...');
phantom.exit(1);
}, timeout * 1000);
}

// Do nothing... the callback mechanism will handle everything!
}
});

function addLogging() {
window.document.addEventListener('DOMContentLoaded', function() {
var currentTestAssertions = [];

QUnit.log(function(details) {
var response;

// Ignore passing assertions
if (details.result) {
return;
}

response = details.message || '';

if (typeof details.expected !== 'undefined') {
if (response) {
response += ', ';
}

response += 'expected: ' + details.expected + ', but was: ' + details.actual;
}

if (details.source) {
response += "\n" + details.source;
}

currentTestAssertions.push('Failed assertion: ' + response);
});

QUnit.testDone(function(result) {
var i,
len,
name = result.module + ': ' + result.name;

if (result.failed) {
console.log('Test failed: ' + name);

for (i = 0, len = currentTestAssertions.length; i < len; i++) {
console.log(' ' + currentTestAssertions[i]);
}
}

currentTestAssertions.length = 0;
});

QUnit.done(function(result) {
console.log('Took ' + result.runtime + 'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.');

if (typeof window.callPhantom === 'function') {
window.callPhantom({
'name': 'QUnit.done',
'data': result
});
}
});
}, false);
}
})();
64 changes: 64 additions & 0 deletions test/run-slimerjs-compare.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash

[ -z $SLIMERJS ] && SLIMERJS=slimerjs
[ -z $GIT ] && GIT=git

PROFILE=`pwd`/profile

BASE_COMMIT=$2

if [[ -z "$BASE_COMMIT" ]]; then
echo "Abort: No base commit set."

exit 1
fi

if [[ ! -z $($GIT status --porcelain --u=no 2> /dev/null) ]]; then
echo "Abort: Directory is not clean. Not running compare to prevent data loss."

exit 1
fi

echo 'Comparing screenshots from '$BASE_COMMIT

echo 'Checking out '$BASE_COMMIT'...'
$GIT checkout --detach $BASE_COMMIT 2>/dev/null

echo 'Taking screenshots...'

mkdir -p $PROFILE

$SLIMERJS --local-storage-quota=50000000 -profile $PROFILE \
./test/headless-runner.js $1?savemode=true |\
tee ./slimerjs.log

# Figure out the exit code ourselves because Gecko does not allow
# SlimerJS to do so for now.
ERROR=0
[ -z "`grep ' 0 failed.' ./slimerjs.log`" ] && ERROR=1

if [ $ERROR -ne 0 ]; then
rm ./slimerjs.log
rm -rf $PROFILE

exit $ERROR
fi

echo

echo 'Go back to the previous checkout ...'
$GIT checkout - 2>/dev/null

echo 'Comparing screenshots...'

$SLIMERJS -profile $PROFILE ./test/headless-runner.js $1?allownoref=true |\
tee ./slimerjs.log

# Figure out the exit code ourselves because Gecko does not allow
# SlimerJS to do so for now.
[ -z "`grep ' 0 failed.' ./slimerjs.log`" ] && ERROR=1

rm ./slimerjs.log
rm -rf $PROFILE

exit $ERROR
13 changes: 13 additions & 0 deletions test/run-slimerjs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

[ -z $SLIMERJS ] && SLIMERJS=slimerjs

echo 'Testing '$1

$SLIMERJS ./test/headless-runner.js $1 | tee ./slimerjs.log

# Figure out the exit code ourselves because Gecko does not allow
# SlimerJS to do so for now.
[ -z "`grep '0 failed.' ./slimerjs.log`" ] && ERROR=1
rm ./slimerjs.log
exit $ERROR

0 comments on commit 335cf10

Please sign in to comment.