From 0cb43d5e8a044db73bb13698137c444c05b8fd47 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Mon, 5 Mar 2018 16:22:13 -0500 Subject: [PATCH] progtest: Do not run tests async on console Performance hit is too great; automated tests need to be _fast_! * src/AsyncTestRunner.js: New TestRunner subtype. * src/TestRunner.js (_runAsync): Rename to virtual protected `runAllTests'; this method is overridden by aforementioned subtype. * src/env.js: Use it. --- progtest/src/AsyncTestRunner.js | 74 +++++++++++++++++++++++++++++++++ progtest/src/TestRunner.js | 38 ++++------------- progtest/src/env.js | 30 ++++++++----- 3 files changed, 102 insertions(+), 40 deletions(-) create mode 100644 progtest/src/AsyncTestRunner.js diff --git a/progtest/src/AsyncTestRunner.js b/progtest/src/AsyncTestRunner.js new file mode 100644 index 00000000..99330864 --- /dev/null +++ b/progtest/src/AsyncTestRunner.js @@ -0,0 +1,74 @@ +/** + * Async test case runner + * + * 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 . + */ + +"use strict"; + +const { Class } = require( 'easejs' ); +const TestRunner = require( './TestRunner' ); + + +/** + * Run test cases asynchronously and report results + * + * This allows the browser to repaint between cases. + */ +module.exports = Class( 'TestRunner' ) + .extend( TestRunner, +{ + /** + * Run all tests asynchronously + * + * TODO: This significantly slows down the runner! The better option + * would be to go back to sync and put it in a Web Worker in the client, + * which would also async updating of the UI. + * + * @param {Array} dfns test case definitions + * + * @return {Promise} promise to complete test cases, yielding results + */ + 'override protected runAllTests'( dfns ) + { + const total = dfns.length; + + return new Promise( ( resolve, reject ) => + { + const results = []; + + const runNext = () => + { + if ( dfns.length === 0 ) + { + resolve( results ); + return; + } + + const dfn = dfns.shift(); + const result = this.runTest( dfn, results.length, total ); + + results.push( result ); + + setTimeout( runNext, 0 ); + }; + + runNext(); + } ); + }, +} ); diff --git a/progtest/src/TestRunner.js b/progtest/src/TestRunner.js index abbdda1b..1fc7b1c1 100644 --- a/progtest/src/TestRunner.js +++ b/progtest/src/TestRunner.js @@ -76,49 +76,29 @@ module.exports = Class( 'TestRunner', this._reporter.preRun( total ); - return this._runAsync( dfns ).then( + return this.runAllTests( dfns ).then( results => ( this._reporter.done( results ), results ) ); }, /** - * Run all tests asynchronously + * Run all tests * - * TODO: This significantly slows down the runner! The better option - * would be to go back to sync and put it in a Web Worker in the client, - * which would also async updating of the UI. + * This may be overridden by subtypes to change how the tests are run + * (for example, to run each asynchronously). * * @param {Array} dfns test case definitions * * @return {Promise} promise to complete test cases, yielding results */ - 'private _runAsync'( dfns ) + 'virtual protected runAllTests'( dfns ) { const total = dfns.length; - return new Promise( ( resolve, reject ) => - { - const results = []; - - const runNext = () => - { - if ( dfns.length === 0 ) - { - resolve( results ); - return; - } - - const dfn = dfns.shift(); - const result = this._runTest( dfn, results.length, total ); - - results.push( result ); - - setTimeout( runNext, 0 ); - }; - - runNext(); - } ); + return Promise.resolve( + dfns.map( ( dfn, i ) => this.runTest( dfn, ( i + 1 ), total ) ) + ); }, @@ -131,7 +111,7 @@ module.exports = Class( 'TestRunner', * * @return {Object} test results */ - 'private _runTest'( { description: desc, data, expect }, test_i, total ) + 'protected runTest'( { description: desc, data, expect }, test_i, total ) { // no input map---#rate uses params directly const result = this._tryRun( data ); diff --git a/progtest/src/env.js b/progtest/src/env.js index 7072791c..78a97ecc 100644 --- a/progtest/src/env.js +++ b/progtest/src/env.js @@ -26,6 +26,7 @@ const yaml_reader = require( 'js-yaml' ); const { TestCase, TestRunner, + AsyncTestRunner, reader: { ConstResolver, @@ -41,13 +42,26 @@ const { module.exports = { - console: ( program, stdout, reporter ) => - { - const runner = TestRunner( - ( reporter || ConsoleTestReporter( stdout ) ), + console: ( program, stdout ) => module.exports.common( + program, + stdout, + TestRunner( + ConsoleTestReporter( stdout ), program - ); + ) + ), + browser: ( program, stdout ) => module.exports.common( + program, + stdout, + AsyncTestRunner( + ConsoleTestReporter.use( HtmlConsoleOutput )( stdout ), + program + ) + ), + + common: ( program, stdout, runner ) => + { const reader = YamlTestReader .use( DateResolver ) .use( ConstResolver( program ) ) @@ -71,10 +85,4 @@ module.exports = { } } ); }, - - browser: ( program, stdout ) => module.exports.console( - program, - stdout, - ConsoleTestReporter.use( HtmlConsoleOutput )( stdout ) - ), };