diff --git a/src/builder.js b/src/builder.js index 637107d..12e3ad4 100644 --- a/src/builder.js +++ b/src/builder.js @@ -226,6 +226,10 @@ exports.build = function(spec, progressCallback, resultCallback) { grade: [ 'hidden', function(results, next) { let result = { json: { public: results.public.result, hidden: results.hidden.result } }; grader.grade(spec, results.builddir, result, buildOutputBase(spec, results.builder, 'grade'), next); + } ], + passfail: [ 'hidden', function(results, next) { + let result = { json: { public: results.public.result, hidden: results.hidden.result } }; + exports.passfail(spec, results.builddir, result, buildOutputBase(spec, results.builder, 'passfail'), next); } ] }, function(err, results) { log.info('build complete'); @@ -246,6 +250,8 @@ exports.build = function(spec, progressCallback, resultCallback) { if (results.grade) { results.grade = [ results.grade.score, results.grade.outof ]; } + // and don't store pass/fail + delete results.passfail; fs.writeFile(buildResultFile(spec), JSON.stringify(results), function(fserr) { if (fserr) { log.error({ err: fserr, results }, 'error writing results'); } @@ -260,7 +266,32 @@ exports.build = function(spec, progressCallback, resultCallback) { } }); }); -} +}; + +exports.passfail = function(spec, builddir, build, output, callback) { + let passfail = { spec, public: {}, hidden: {} }; + for (let [ report, testsuites ] of [ + [ passfail.public, build.json.public && build.json.public.testsuites || [] ], + [ passfail.hidden, build.json.hidden && build.json.hidden.testsuites || [] ], + ]) { + for (let suite of testsuites) { + let pkg = report[suite.package] || (report[suite.package] = {}); + let cls = pkg[suite.name] = Object.assign({}, suite); + [ 'hostname' ].forEach(reject => delete cls[reject]); + cls.testcases = {}; + for (let testcase of suite.testcases) { + let test = cls.testcases[testcase.name] = Object.assign({}, testcase); + [ 'classname', 'name', 'time' ].forEach(reject => delete test[reject]); + } + } + } + fs.writeFile(output + '.json', JSON.stringify(passfail), function(err) { + if (err) { + err.dmesg = 'error writing pass/fail report'; + } + callback(err, passfail); + }); +}; // command-line build if (require.main === module) { diff --git a/test/builder.js b/test/builder.js index 6ddc1ab..97da417 100644 --- a/test/builder.js +++ b/test/builder.js @@ -236,6 +236,7 @@ describe('builder', function() { results.public.should.be.type('boolean'); results.hidden.should.be.type('boolean'); results.grade.should.be.an.instanceof(Array); + should.not.exist(results.passfail); results.started.should.be.within(start, finish); results.finished.should.be.within(start, finish); done(err); @@ -287,6 +288,18 @@ describe('builder', function() { }); }); }); + it('should record test results', function(done) { + builder.build(spec, function() { }, function(err, results) { + fs.readFile(path.join(resultdir, results.builder, 'passfail.json'), { encoding: 'utf8' }, function(fserr, data) { + let json = JSON.parse(data); + json.public['']['FakePublic'].testcases['publicPass'].should.eql({}); + json.public['']['FakePublic'].testcases['publicFail'].should.eql({ failure: 'Fake failure!' }); + json.hidden['']['FakeHidden'].testcases['hiddenPass'].should.eql({}); + json.hidden['']['FakeHidden'].testcases['hiddenError'].should.eql({ error: 'Fake error!' }); + done(err || fserr); + }); + }); + }); it('should schedule build directory for deletion', function(done) { sandbox.useFakeTimers('setTimeout'); builder.build(spec, function() { }, function(err, results) { diff --git a/test/fixtures/builder/build/should-record-test-results/build/build.xml b/test/fixtures/builder/build/should-record-test-results/build/build.xml new file mode 100644 index 0000000..2cb0403 --- /dev/null +++ b/test/fixtures/builder/build/should-record-test-results/build/build.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + Fake failure! + + + + + + + + + + + + + + + + + + Fake error! + + + + + + + + + + + + +