test: add performance tests

pull/321/merge
Estevao Soares dos Santos 2016-12-23 09:29:58 +00:00
parent 60a9467e3d
commit 43ff0b643e
12 changed files with 319 additions and 7 deletions

View File

@ -188,8 +188,16 @@ module.exports = function (grunt) {
grunt.task.run(['lint', 'concat:test', 'simplemocha:single', 'clean']);
});
grunt.registerTask('performancejs', function () {
'use strict';
var perf = require('./test/node/performance.js');
perf.runTests();
perf.generateLogs();
});
grunt.registerTask('lint', ['jshint', 'jscs']);
grunt.registerTask('test', ['clean', 'lint', 'concat:test', 'simplemocha:node', 'clean']);
grunt.registerTask('performance', ['concat:test', 'performancejs', 'clean']);
grunt.registerTask('build', ['test', 'concat:dist', 'uglify', 'endline']);
grunt.registerTask('prep-release', ['build', 'conventionalChangelog']);

17
dist/showdown.js vendored
View File

@ -1,4 +1,4 @@
;/*! showdown 21-12-2016 */
;/*! showdown 23-12-2016 */
(function(){
/**
* Created by Tivie on 13-07-2015.
@ -110,6 +110,18 @@ function getDefaultOpts(simple) {
}
return ret;
}
function allOptionsOn() {
'use strict';
var options = getDefaultOpts(true),
ret = {};
for (var opt in options) {
if (options.hasOwnProperty(opt)) {
ret[opt] = true;
}
}
return ret;
}
/**
* Created by Tivie on 06-01-2015.
@ -136,7 +148,8 @@ var showdown = {},
simpleLineBreaks: true,
requireSpaceBeforeHeadingText: true
},
vanilla: getDefaultOpts(true)
vanilla: getDefaultOpts(true),
allOn: allOptionsOn()
};
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -52,8 +52,10 @@
"grunt-simple-mocha": "^0.4.0",
"js-beautify": "^1.5.6",
"load-grunt-tasks": "^3.2.0",
"performance-now": "^0.2.0",
"quiet-grunt": "^0.2.3",
"semver": "^5.0.0",
"semver-sort": "0.0.4",
"sinon": "^1.14.1",
"source-map-support": "^0.2.9"
},

1
performance.json Normal file
View File

@ -0,0 +1 @@
{"1.5.4":[{"suiteName":"Basic","cycles":100,"tests":[{"name":"Simple \"Hello World\"","time":0.30990324000000025,"maxTime":5.549075,"minTime":0.14916800000000308},{"name":"readme.md","time":8.072704459999997,"maxTime":17.975579000000003,"minTime":7.220064999999977}]}]}

10
performance.log.md Normal file
View File

@ -0,0 +1,10 @@
# Performance Tests for showdown
## [version 1.5.4](https://github.com/showdownjs/showdown/tree/)
### Test Suite: Basic (100 cycles)
- **Simple "Hello World":** took 0.310ms (*max: 5.549ms; min: 0.149ms*)
- **readme.md:** took 8.073ms (*max: 17.976ms; min: 7.220ms*)

View File

@ -108,3 +108,15 @@ function getDefaultOpts(simple) {
}
return ret;
}
function allOptionsOn() {
'use strict';
var options = getDefaultOpts(true),
ret = {};
for (var opt in options) {
if (options.hasOwnProperty(opt)) {
ret[opt] = true;
}
}
return ret;
}

View File

@ -23,7 +23,8 @@ var showdown = {},
simpleLineBreaks: true,
requireSpaceBeforeHeadingText: true
},
vanilla: getDefaultOpts(true)
vanilla: getDefaultOpts(true),
allOn: allOptionsOn()
};
/**

38
test/node/performance.js Normal file
View File

@ -0,0 +1,38 @@
/**
* Created by Tivie on 21/12/2016.
*/
'use strict';
var fs = require('fs'),
showdown = require('../bootstrap').showdown,
converter = new showdown.Converter(),
pkg = require('../../package.json'),
performance = require('../performance/performance.js');
performance.setLibraryName(pkg.name);
performance.setVersion(pkg.version);
performance.setGithubLink('https://github.com/showdownjs/showdown/tree/');
var
runTests = function () {
new performance.Suite('Basic')
.setOption('cycles', 100)
.add('Simple "Hello World"', function () {
converter.makeHtml('*Hello* **World**!');
})
.add('readme.md', {
prepare: function () {
return fs.readFileSync('README.md', 'utf8');
},
test: function (mdText) {
converter.makeHtml(mdText);
}
});
},
generateLogs = function () {
performance.generateLog();
};
module.exports = {
runTests: runTests,
generateLogs: generateLogs
};

View File

@ -0,0 +1,227 @@
/**
* Created by Tivie on 21/12/2016.
*/
'use strict';
var now = require('performance-now'),
fs = require('fs'),
semverSort = require('semver-sort'),
performance = {
version: '',
libraryName: '',
MDFile: 'performance.log.md',
logFile: 'performance.json',
testSuites: [],
silent: false,
githubLink: ''
};
performance.setVersion = function (version) {
performance.version = version;
};
performance.setLibraryName = function (name) {
performance.libraryName = name;
};
performance.setGithubLink = function (url) {
performance.githubLink = url;
};
performance.generateLog = function (filename, MDFilename) {
filename = filename || performance.logFile;
MDFilename = MDFilename || performance.MDFile;
fs.closeSync(fs.openSync(filename, 'a'));
var json = fs.readFileSync(filename),
jsonParsed;
try {
jsonParsed = JSON.parse(json);
}
catch (err) {
jsonParsed = {};
}
var jData = [];
for (var i = 0; i < performance.testSuites.length; ++i) {
// Suite
var suiteName = performance.testSuites[i].getSuiteName(),
cycles = performance.testSuites[i].getOption('cycles'),
subJData = {
suiteName: suiteName,
cycles: cycles,
tests: []
},
testSuite = performance.testSuites[i].getTests();
//make sure tests have ran first
if (!performance.testSuites[i].hasRun()) {
performance.testSuites[i].run();
}
// loop through tests
for (var ii = 0; ii < testSuite.length; ++ii) {
// Test
var test = testSuite[ii];
subJData.tests.push({
name: test.name,
time: test.time,
maxTime: test.maxTime,
minTime: test.minTime
});
}
jData.push(subJData);
}
jsonParsed[performance.version] = jData;
//Sort jsonParsed
var versions = [];
for (var version in jsonParsed) {
if (jsonParsed.hasOwnProperty(version)) {
versions.push(version);
}
}
semverSort.desc(versions);
var finalJsonObj = {};
for (i = 0; i < versions.length; ++i) {
if (jsonParsed.hasOwnProperty(versions[i])) {
finalJsonObj[versions[i]] = jsonParsed[versions[i]];
}
}
fs.writeFileSync(filename, JSON.stringify(finalJsonObj));
generateMD(MDFilename, finalJsonObj);
};
function generateMD(filename, obj) {
fs.closeSync(fs.openSync(filename, 'w'));
// generate MD
var otp = '# Performance Tests for ' + performance.libraryName + '\n\n\n';
for (var version in obj) {
if (obj.hasOwnProperty(version)) {
otp += '## [version ' + version + '](' + performance.githubLink + ')\n\n';
var testSuite = obj[version];
for (var i = 0; i < testSuite.length; ++i) {
otp += '### Test Suite: ' + testSuite[i].suiteName + ' (' + testSuite[i].cycles + ' cycles)\n';
var tests = testSuite[i].tests;
for (var ii = 0; ii < tests.length; ++ii) {
var time = parseFloat(tests[ii].time).toFixed(3),
maxTime = parseFloat(tests[ii].maxTime).toFixed(3),
minTime = parseFloat(tests[ii].minTime).toFixed(3);
otp += ' - **' + tests[ii].name + ':** took ' + time + 'ms (*max: ' + maxTime + 'ms; min: ' + minTime + 'ms*)\n';
}
otp += '\n';
}
otp += '\n';
}
}
fs.writeFileSync(filename, otp);
}
performance.Suite = function (name) {
var suiteName = name || '',
tests = [],
hasRunFlag = false,
options = {
cycles: 20
};
this.setOption = function (key, val) {
options[key] = val;
return this;
};
this.getOption = function (key) {
return options[key];
};
this.add = function (name, obj) {
if (typeof obj === 'function') {
obj = {
prepare: function () {},
test: obj,
teardown: function () {}
};
}
if (!obj.hasOwnProperty('test')) {
throw 'obj must have a property called test';
}
if (typeof obj.test !== 'function') {
throw 'obj test property must be a function';
}
if (!obj.hasOwnProperty('prepare')) {
obj.prepare = function () {};
}
if (!obj.hasOwnProperty('teardown')) {
obj.teardown = function () {};
}
if (typeof obj.prepare !== 'function') {
throw 'obj prepare property must be a function';
}
if (typeof obj.teardown !== 'function') {
throw 'obj teardown property must be a function';
}
tests.push({
name: name,
obj: obj,
time: 0,
maxTime: 0,
minTime: 0
});
return this;
};
this.run = function run () {
var nn = options.cycles;
console.log('running tests: ' + nn + ' cycles each.');
for (var i = 0; i < tests.length; ++i) {
var times = [],
passVar = tests[i].obj.prepare();
for (var ii = 0; ii < nn; ++ii) {
var before = now();
tests[i].obj.test(passVar);
var after = now();
times.push(after - before);
}
var total = times.reduce(function (a, b) {return a + b;}, 0);
tests[i].time = total / options.cycles;
tests[i].minTime = Math.min.apply(null, times);
tests[i].maxTime = Math.max.apply(null, times);
if (!options.silent) {
console.log(tests[i].name + ' took an average of ' + tests[i].time + 'ms (min: ' + tests[i].minTime + 'ms; max: ' + tests[i].maxTime + 'ms');
}
}
hasRunFlag = true;
return this;
};
this.hasRun = function () {
return hasRunFlag;
};
this.getSuiteName = function () {
return suiteName;
};
this.getTests = function () {
return tests;
};
performance.testSuites.push(this);
};
module.exports = performance;