diff options
author | Mike Gerwitz <mike.gerwitz@rtspecialty.com> | 2018-02-16 12:19:37 -0500 |
---|---|---|
committer | Mike Gerwitz <mike.gerwitz@rtspecialty.com> | 2018-02-19 15:21:14 -0500 |
commit | 47f0f4039b9c6d4a9898714dcca4692fd8af154a (patch) | |
tree | 2b92cae5fa2c0e57b474a4652aee2da7a7358513 /progtest/test | |
parent | 0c020b736d8d46f18e2e671d7b928e146db5572e (diff) | |
download | tame-47f0f4039b9c6d4a9898714dcca4692fd8af154a.tar.gz tame-47f0f4039b9c6d4a9898714dcca4692fd8af154a.tar.bz2 tame-47f0f4039b9c6d4a9898714dcca4692fd8af154a.zip |
progtest: Initial working console runner
Diffstat (limited to 'progtest/test')
-rw-r--r-- | progtest/test/TestCaseTest.js | 99 | ||||
-rw-r--r-- | progtest/test/TestRunnerTest.js | 144 | ||||
-rw-r--r-- | progtest/test/reader/ConstResolverTest.js | 104 | ||||
-rw-r--r-- | progtest/test/reader/DateResolverTest.js | 85 | ||||
-rw-r--r-- | progtest/test/reader/YamlTestReaderTest.js | 55 | ||||
-rw-r--r-- | progtest/test/reporter/ConsoleTestReporterTest.js | 177 |
6 files changed, 664 insertions, 0 deletions
diff --git a/progtest/test/TestCaseTest.js b/progtest/test/TestCaseTest.js new file mode 100644 index 0000000..95b46d6 --- /dev/null +++ b/progtest/test/TestCaseTest.js @@ -0,0 +1,99 @@ +/** + * Tests TestCase + * + * Copyright (C) 2018 R-T Specialty, LLC. + * + * This file is part of TAME. + * + * TAME is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +"use strict"; + +const { expect } = require( 'chai' ); +const Sut = require( '../src/TestCase' ); + + +describe( "TestCase", () => +{ + it( "allows retrieving raw data", () => + { + const data = { + description: "Foo bar", + data: { foo: [ 5 ] }, + expect: { bar: [ 1 ] }, + }; + + const sut = Sut( data ); + + expect( sut.description ).to.equal( data.description ); + expect( sut.data ).to.deep.equal( data.data ); + expect( sut.expect ).to.deep.equal( data.expect ); + } ); + + + it( "provides sane defaults for missing data", () => + { + const sut = Sut( {} ); + + expect( sut.description ).to.equal( "" ); + expect( sut.data ).to.deep.equal( {} ); + expect( sut.expect ).to.deep.equal( {} ); + } ); + + + describe( "#mapEachValue", () => + { + it( "visits each 'data' and 'expect' value", () => + { + // tests scalar, vector, matrix; mixed with non-constants + const testcase = { + description: 'test desc', + + data: { + foo: 'bar', + bar: [ 'baz', 'quux' ], + baz: [ [ 'quuux', 'foox' ], [ 'moo', 'cow' ] ], + }, + expect: { + quux: 'out', + quuux: [ 'of', 'names' ], + }, + }; + + const expected = { + data: { + foo: 'OKbar', + bar: [ 'OKbaz', 'OKquux' ], + baz: [ [ 'OKquuux', 'OKfoox' ], [ 'OKmoo', 'OKcow' ] ], + }, + expect: { + quux: 'OKout', + quuux: [ 'OKof', 'OKnames' ], + }, + }; + + const result = Sut( testcase ).mapEachValue( val => `OK${val}` ); + + // derived from the original + expect( result.description ).to.equal( testcase.description ); + expect( result.data ).to.deep.equal( expected.data ); + expect( result.expect ).to.deep.equal( expected.expect ); + + // but not the original (should return a new object) + expect( result.data ).to.not.equal( testcase.data ); + expect( result.expect ).to.not.equal( testcase.expect ); + } ); + } ); +} ); diff --git a/progtest/test/TestRunnerTest.js b/progtest/test/TestRunnerTest.js new file mode 100644 index 0000000..fc06e04 --- /dev/null +++ b/progtest/test/TestRunnerTest.js @@ -0,0 +1,144 @@ +/** + * Tests TestReader + * + * Copyright (C) 2018 R-T Specialty, LLC. + * + * This file is part of TAME. + * + * TAME is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +"use strict"; + +const { expect } = require( 'chai' ); +const { Class } = require( 'easejs' ); +const Sut = require( '../src/TestRunner' ); +const TestReporter = require( '../src/reporter/TestReporter' ); +const NullTestReporter = require( '../src/reporter/NullTestReporter' ); + + +describe( "TestRunner", () => +{ + it( "runs each test against given program", () => + { + const given = []; + + const program = { + rater( data ) + { + return rate_results[ given.push( data ) - 1 ]; + } + }; + + const test_cases = [ + { + description: "first", + data: { a: 1 }, + expect: { foo: 1 }, + }, + { + description: "second", + data: { a: 2 }, + expect: { + foo: [ 1, 2 ], + bar: [ 3, 1 ], + baz: [ 4, 2 ], + }, + }, + ]; + + const rate_results = [ + // no failures + { vars: { foo: 1 } }, + + // bar, baz failures + { vars: { + foo: [ 1, 2 ], + bar: [ 3, 4 ], + baz: [ 4, 5 ], + } }, + ]; + + const expect_failures = [ + [], + [ + { + field: 'bar', + expect: test_cases[ 1 ].expect.bar, + result: rate_results[ 1 ].vars.bar, + }, + { + field: 'baz', + expect: test_cases[ 1 ].expect.baz, + result: rate_results[ 1 ].vars.baz, + }, + ] + ]; + + const results = Sut( NullTestReporter(), program ) + .runTests( test_cases ); + + test_cases.forEach( ( test_case, i ) => + { + const result = results[ i ]; + + expect( result.desc ).to.equal( test_case.description ); + expect( result.i ).to.equal( i ); + expect( result.total ).to.equal( + Object.keys( test_case.expect ).length + ); + expect( result.failures ).to.deep.equal( expect_failures[ i ] ); + } ); + } ); + + + it( "invokes reporter before, during, and after test cases", done => + { + let pre = false; + let results = []; + + const program = { rater: () => ( { vars: {} } ) }; + + const mock_reporter = Class.implement( TestReporter ).extend( + { + preRun( total ) + { + expect( total ).to.equal( 2 ); + pre = true; + }, + + testCaseResult( result, total ) + { + expect( pre ).to.equal( true ); + expect( total ).to.equal( 2 ); + + results.push( result ); + }, + + done( given_results ) + { + expect( pre ).to.equal( true ); + expect( results ).to.deep.equal( given_results ); + + done(); + }, + } )(); + + // see done() above + Sut( mock_reporter, program ).runTests( [ + { description: '', data: {}, expect: {} }, + { description: '', data: {}, expect: {} }, + ] ); + } ); +} ); diff --git a/progtest/test/reader/ConstResolverTest.js b/progtest/test/reader/ConstResolverTest.js new file mode 100644 index 0000000..2060f2a --- /dev/null +++ b/progtest/test/reader/ConstResolverTest.js @@ -0,0 +1,104 @@ +/** + * Tests ConstResolver + * + * Copyright (C) 2018 R-T Specialty, LLC. + * + * This file is part of TAME. + * + * TAME is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +"use strict"; + +const { expect } = require( 'chai' ); +const { Class } = require( 'easejs' ); +const TestCase = require( '../../src/TestCase' ); +const TestReader = require( '../../src/reader/TestReader' ); +const Sut = require( '../../src/reader/ConstResolver' ); + +const StubTestReader = Class.implement( TestReader ).extend( +{ + constructor( parsed_data ) + { + this.parsedData = parsed_data; + }, + + 'virtual public loadCases'( _ ) + { + return this.parsedData; + } +} ); + + +describe( "ConstResolver", () => +{ + [ 'data', 'expect' ].forEach( field => + { + it( `replaces known ${field} constants from program`, () => + { + const program = { + rater: { + consts: { FOO: 1, BAR: 2 }, + }, + }; + + // tests scalar, vector, matrix; mixed with non-constants + const parsed_data = [ + TestCase( { [field]: { foo: 'FOO', bar: 4 } } ), + TestCase( + { [field]: { + foo: [ 'FOO', 'BAR', 5 ], + bar: [ [ 'FOO', 3 ], [ 'FOO', 'BAR' ] ], + } } + ), + ]; + + const { FOO, BAR } = program.rater.consts; + + const expected = [ + TestCase( { [field]: { foo: FOO, bar: 4 } } ), + TestCase( + { [field]: { + foo: [ FOO, BAR, 5 ], + bar: [ [ FOO, 3 ], [ FOO, BAR ] ], + } } + ), + ]; + + // anything just to proxy + const given_yaml = 'fooml'; + + const result = StubTestReader + .use( Sut( program ) )( parsed_data ) + .loadCases( given_yaml ); + + result.forEach( + ( tcase, i ) => expect( tcase[ field ] ) + .to.deep.equal( expected[ i ][ field ] ) + ); + } ); + + + it( `throws error on unknown $field constant`, () => + { + const program = { rater: { consts: {} } }; + const parsed_data = [ TestCase( { [field]: { foo: 'UNKNOWN' } } ) ]; + + expect( + () => StubTestReader.use( Sut( program ) )( parsed_data ) + .loadCases( '' ) + ).to.throw( Error, 'UNKNOWN' ); + } ); + } ); +} ); diff --git a/progtest/test/reader/DateResolverTest.js b/progtest/test/reader/DateResolverTest.js new file mode 100644 index 0000000..4b2225d --- /dev/null +++ b/progtest/test/reader/DateResolverTest.js @@ -0,0 +1,85 @@ +/** + * Tests DateResolver + * + * Copyright (C) 2018 R-T Specialty, LLC. + * + * This file is part of TAME. + * + * TAME is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +"use strict"; + +const { expect } = require( 'chai' ); +const { Class } = require( 'easejs' ); +const TestCase = require( '../../src/TestCase' ); +const TestReader = require( '../../src/reader/TestReader' ); +const Sut = require( '../../src/reader/DateResolver' ); + +const MockTestReader = Class.implement( TestReader ).extend( +{ + constructor( parsed_data, expected_load ) + { + this.parsedData = parsed_data; + this.expectedLoad = expected_load; + }, + + 'virtual public loadCases'( given ) + { + expect( given ).to.equal( this.expectedLoad ); + return this.parsedData; + } +} ); + + +describe( "DateResolver", () => +{ + [ 'data', 'expect' ].forEach( field => + { + it( `converts ${field} dates into Unix timestamps`, () => + { + const date = '10/25/1989'; + const time = ( new Date( date ) ).getTime() / 1000; + + // tests scalar, vector, matrix; mixed with non-constants + const parsed_data = [ + TestCase( + { [field]: { + foo: [ 5, 'NOTADATE', date ], + } } + ), + ]; + + const expected = [ + TestCase( + { [field]: { + foo: [ 5, 'NOTADATE', time ], + } } + ), + ]; + + // anything just to proxy + const given_yaml = 'fooml'; + + const result = MockTestReader + .use( Sut )( parsed_data, given_yaml ) + .loadCases( given_yaml ); + + result.forEach( + ( tcase, i ) => expect( tcase[ field ] ) + .to.deep.equal( expected[ i ][ field ] ) + ); + } ); + } ); +} ); diff --git a/progtest/test/reader/YamlTestReaderTest.js b/progtest/test/reader/YamlTestReaderTest.js new file mode 100644 index 0000000..9fb26fd --- /dev/null +++ b/progtest/test/reader/YamlTestReaderTest.js @@ -0,0 +1,55 @@ +/** + * Tests TestReader + * + * Copyright (C) 2018 R-T Specialty, LLC. + * + * This file is part of TAME. + * + * TAME is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +"use strict"; + +const { expect } = require( 'chai' ); +const Sut = require( '../../src/reader/YamlTestReader' ); + + +describe( "YamlTestReader", () => +{ + it( "parses given yaml", () => + { + const yaml = "foo: bar"; + + const parsed = [ + { + description: "first desc", + data: { "foo": "bar" }, + expect: { "bar": "baz" }, + }, + ]; + + const case_ctor = ( data ) => ( { ok: data } ); + + const mock_parser = { + safeLoad( given ) + { + expect( given ).to.equal( yaml ); + return parsed; + } + }; + + expect( Sut( mock_parser, case_ctor ).loadCases( yaml ) ) + .to.deep.equal( [ { ok: parsed[0] } ] ); + } ); +} ); diff --git a/progtest/test/reporter/ConsoleTestReporterTest.js b/progtest/test/reporter/ConsoleTestReporterTest.js new file mode 100644 index 0000000..07e3e52 --- /dev/null +++ b/progtest/test/reporter/ConsoleTestReporterTest.js @@ -0,0 +1,177 @@ +/** + * Tests ConsoleTestReporter + * + * Copyright (C) 2018 R-T Specialty, LLC. + * + * This file is part of TAME. + * + * TAME is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +"use strict"; + +const { expect } = require( 'chai' ); +const Sut = require( '../../src/reporter/ConsoleTestReporter' ); + + +describe( "ConsoleTestReporter", () => +{ + describe( "#testCaseResult", () => + { + it( "outputs indicator for each test case", () => + { + let output = ''; + + const stdout = { write: str => output += str }; + const sut = Sut( stdout ); + + [ + { i: 0, failures: [] }, + { i: 1, failures: [] }, + { i: 2, failures: [ {} ] }, + { i: 3, failures: [ {}, {} ] }, + { i: 4, failures: [] }, + ].forEach( + result => sut.testCaseResult( result, 5 ) + ); + + expect( output ).to.equal( '..FF.' ); + } ); + + + it( "outputs line break with count after 40 cases", () => + { + let output = ''; + + const stdout = { write: str => output += str }; + const sut = Sut( stdout ); + + const results = ( new Array( 130 ) ).join( '.' ).split( '.' ) + .map( ( _, i ) => ( { i: i, failures: [] } ) ); + + results.forEach( + result => sut.testCaseResult( result, 130 ) + ); + + expect( output ).to.equal( + ( new Array( 51 ) ).join( '.' ) + ' 50/130\n' + + ( new Array( 51 ) ).join( '.' ) + ' 100/130\n' + + ( new Array( 31 ) ).join( '.' ) + ); + } ); + } ); + + + describe( "done", () => + { + it( "outputs report of failures to stdout", () => + { + let output = ''; + + const stdout = { write: str => output += str }; + + const results = [ + { i: 0, total: 1, desc: "test 0", failures: [] }, + { i: 1, total: 2, desc: "test 1", failures: [] }, + + { + i: 2, + total: 3, + desc: "test 2", + failures: [ + { + field: "foo", + expect: [ 1 ], + result: [ 2, 3 ] + }, + ], + }, + { + i: 3, + total: 4, + desc: "test 3", + failures: [ + { + field: "bar", + expect: 2, + result: 3, + }, + { + field: "baz", + expect: [ [ 4 ] ], + result: [ 5 ], + } + ], + }, + ]; + + const stringified = results.map( + result => result.failures.map( + failure => ( { + expect: JSON.stringify( failure.expect ), + result: JSON.stringify( failure.result ), + } ) + ) + ); + + Sut( stdout ).done( results ); + + const fail_output = output.match( /\n\n\[#3\](.|\n)*\n\n/ )[0]; + + // 1-indexed output + expect( fail_output ).to.equal( + `\n\n` + + `[#3] test 2\n` + + ` foo:\n` + + ` expected: ` + stringified[ 2 ][ 0 ].expect + `\n` + + ` result: ` + stringified[ 2 ][ 0 ].result + `\n` + + `\n` + + `[#4] test 3\n` + + ` bar:\n` + + ` expected: ` + stringified[ 3 ][ 0 ].expect + `\n` + + ` result: ` + stringified[ 3 ][ 0 ].result + `\n` + + ` baz:\n` + + ` expected: ` + stringified[ 3 ][ 1 ].expect + `\n` + + ` result: ` + stringified[ 3 ][ 1 ].result + `\n\n` + ); + } ); + + + it( "outputs summary on last line of stdout", () => + { + let output = ''; + + const stdout = { write: str => output += str }; + const sut = Sut( stdout, {} ); + + Sut( stdout ).done( [ + { i: 0, total: 1, failures: [] }, + { i: 1, total: 2, failures: [] }, + { i: 2, total: 3, failures: [ {} ] }, + { i: 3, total: 4, failures: [ {}, {} ] }, + { i: 4, total: 5, failures: [] }, + ] ); + + const lines = output.split( '\n' ); + + // preceded by empty line + expect( lines[ lines.length - 2 ] ).to.equal( "" ); + + // last line + expect( lines[ lines.length - 1 ] ).to.equal( + `5 tests, 2 failed (15 assertions, 3 failures)` + ); + } ); + } ); +} ); |