diff --git a/progtest/src/TestRunner.js b/progtest/src/TestRunner.js index b7685dc3..abbdda1b 100644 --- a/progtest/src/TestRunner.js +++ b/progtest/src/TestRunner.js @@ -134,7 +134,7 @@ module.exports = Class( 'TestRunner', 'private _runTest'( { description: desc, data, expect }, test_i, total ) { // no input map---#rate uses params directly - const result = this._program.rater( data ).vars; + const result = this._tryRun( data ); const cmp = Object.keys( expect ).map( field => [ @@ -143,12 +143,18 @@ module.exports = Class( 'TestRunner', ] ); - const failures = cmp.filter( ( [ , ok ] ) => !ok ) - .map( ( [ field ] ) => ( { - field: field, - expect: expect[ field ], - result: result[ field ], - } ) ); + const failures = ( result instanceof Error ) + ? [ { + field: "error", + expect: "", + result: result.message, + } ] + : cmp.filter( ( [ , ok ] ) => !ok ) + .map( ( [ field ] ) => ( { + field: field, + expect: expect[ field ], + result: result[ field ], + } ) ); const succeeded = cmp.length - failures.length; @@ -167,6 +173,30 @@ module.exports = Class( 'TestRunner', }, + /** + * Attempt test case, returning error on failure + * + * If an error is thrown (e.g. terminating classification), it will be + * returned in place of the results. + * + * @param {Object} data input data + * + * @return {Object|Error} result or error + */ + 'private _tryRun'( data ) + { + // no input map---#rate uses params directly + try + { + return this._program.rater( data ).vars; + } + catch( e ) + { + return e; + } + }, + + /** * Recursively compare values (scalar, array) * diff --git a/progtest/test/TestRunnerTest.js b/progtest/test/TestRunnerTest.js index 5a09cfe5..5ca1e741 100644 --- a/progtest/test/TestRunnerTest.js +++ b/progtest/test/TestRunnerTest.js @@ -147,4 +147,37 @@ describe( "TestRunner", () => { description: '', data: {}, expect: {} }, ] ); } ); + + + // exceptions are thrown by terminating classifications + it( "recognizes exception as failure", () => + { + const error_msg = [ "test failure 0", "test failure 1" ]; + + const program = { + rater( data ) + { + throw Error( error_msg.shift() ); + } + }; + + return Sut( NullTestReporter(), program ) + .runTests( [ + { description: '', data: {}, expect: {} }, + { description: '', data: {}, expect: {} }, + ] ) + .then( results => + { + results.forEach( ( { failures }, i ) => + expect( failures ) + .to.deep.equal( [ + { + field: "error", + expect: "", + result: `test failure ${i}`, + }, + ] ) + ); + } ); + } ); } );