diff --git a/progtest/src/TestRunner.js b/progtest/src/TestRunner.js index 5af3d4cb..ee0f4dcc 100644 --- a/progtest/src/TestRunner.js +++ b/progtest/src/TestRunner.js @@ -156,8 +156,8 @@ 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. + * If an error is thrown (e.g. terminating classification or unknown + * input), then it will be returned in place of the results. * * @param {Object} data input data * @@ -168,6 +168,8 @@ module.exports = Class( 'TestRunner', // no input map---#rate uses params directly try { + this._verifyKnownParams( data ); + return this._program.rater( data ).vars; } catch( e ) @@ -177,6 +179,33 @@ module.exports = Class( 'TestRunner', }, + /** + * Verify that all provided inputs match known params + * + * If a given input is not known for the rater for the current program, + * an Error will be thrown with a comma-delimited list of all unknown + * params. + * + * @param {Object} data input data + * + * @return {undefined} + * + * @throws Error when unknown input is found + */ + 'private _verifyKnownParams'( data ) + { + const params = this._program.rater.params || {}; + + const unknown = Object.keys( data ) + .filter( param => params[ param ] === undefined ); + + if ( unknown.length > 0 ) + { + throw Error( "Unknown params: " + unknown.join( ", " ) ); + } + }, + + /** * Recursively compare values (scalar, array) * diff --git a/progtest/test/TestRunnerTest.js b/progtest/test/TestRunnerTest.js index 6d88415d..75e8ed9e 100644 --- a/progtest/test/TestRunnerTest.js +++ b/progtest/test/TestRunnerTest.js @@ -41,6 +41,9 @@ describe( "TestRunner", () => } }; + // `a' is a known param + program.rater.params = { a: {} }; + const test_cases = [ { description: "first", @@ -118,6 +121,32 @@ describe( "TestRunner", () => } ); + it( "fails on unknown params", () => + { + // no params at all are defined + const program = { rater: () => ( { vars: {} } ) }; + + const bad_test = { + description: 'bad param', + data: { + unknown_param_1: 0, + unknown_param_2: 0, + }, + expect: {}, + }; + + return Sut( NullTestReporter(), program ) + .runTests( [ bad_test ] ) + .then( ( [ result ] ) => + { + expect( result.failures[ 0 ].result ) + .to.contain( 'unknown_param_1' ); + expect( result.failures[ 0 ].result ) + .to.contain( 'unknown_param_2' ); + } ); + } ); + + it( "invokes reporter before, during, and after test cases", done => { let pre = false; diff --git a/progtest/test/_stub/program.js b/progtest/test/_stub/program.js index 3f42a984..673ce57e 100644 --- a/progtest/test/_stub/program.js +++ b/progtest/test/_stub/program.js @@ -23,3 +23,6 @@ exports.rater = data => { return { vars: { out: data.in } }; }; + +exports.rater.params = { in: {} }; +