From f375884655e37e38b70c5561a43075c1fdc1a85d Mon Sep 17 00:00:00 2001 From: Yaroslav Admin Date: Thu, 7 May 2020 01:39:53 +0200 Subject: [PATCH] refactor(test): reduce execKarma to a reasonable size (#3496) Finally! Introduced extra step "I wait until server output contains" instead of hard-coded timeout. It will regularly evaluate a condition until it fulfills. This approach should potentially perform a little bit better than the previous solution. --- test/e2e/browser_console.feature | 7 ++- test/e2e/error.feature | 8 +++- test/e2e/pass-opts.feature | 7 ++- test/e2e/step_definitions/core_steps.js | 64 +++++++------------------ test/e2e/step_definitions/utils.js | 15 ++++++ 5 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 test/e2e/step_definitions/utils.js diff --git a/test/e2e/browser_console.feature b/test/e2e/browser_console.feature index 24dc977ed..a83c43e54 100644 --- a/test/e2e/browser_console.feature +++ b/test/e2e/browser_console.feature @@ -183,7 +183,12 @@ Feature: Browser Console Configuration ]; singleRun = false; """ - When I run Karma + When I start a server in background + And I wait until server output contains: + """ + Executed 1 of 1 SUCCESS + """ + And I run Karma Then it passes with like: """ LOG: 'foo' diff --git a/test/e2e/error.feature b/test/e2e/error.feature index 3fd66e173..0b327110e 100644 --- a/test/e2e/error.feature +++ b/test/e2e/error.feature @@ -18,6 +18,7 @@ Feature: Error Display """ SyntaxError: Unexpected token '}' """ + Scenario: Not single-run Syntax Error in a test file Given a configuration with: """ @@ -29,7 +30,12 @@ Feature: Error Display ]; singleRun = false; """ - When I run Karma + When I start a server in background + And I wait until server output contains: + """ + Executed 2 of 2 (1 FAILED) + """ + And I run Karma Then it fails with like: """ SyntaxError: Unexpected token '}' diff --git a/test/e2e/pass-opts.feature b/test/e2e/pass-opts.feature index f8055bb26..f8bc02a61 100644 --- a/test/e2e/pass-opts.feature +++ b/test/e2e/pass-opts.feature @@ -15,7 +15,12 @@ Feature: Passing Options singleRun = false; """ And command line arguments of: "-- arg1 arg2" - When I run Karma + When I start a server in background + And I wait until server output contains: + """ + Executed 1 of 1 (1 FAILED) + """ + And I run Karma Then it passes with no debug: """ . diff --git a/test/e2e/step_definitions/core_steps.js b/test/e2e/step_definitions/core_steps.js index c9c2e5f7b..b328c9051 100644 --- a/test/e2e/step_definitions/core_steps.js +++ b/test/e2e/step_definitions/core_steps.js @@ -2,6 +2,7 @@ const { defineParameterType, Given, Then, When } = require('cucumber') const fs = require('fs') const path = require('path') const { exec } = require('child_process') +const { waitForCondition } = require('./utils') const stopper = require('../../../lib/stopper') let additionalArgs = [] @@ -9,47 +10,13 @@ let additionalArgs = [] function execKarma (command, level, callback) { level = level || 'warn' - const configFile = this.configFile - const runtimePath = this.karmaExecutable - const baseDir = this.workDir - - const executor = (done) => { - const cmd = runtimePath + ' ' + command + ' --log-level ' + level + ' ' + configFile + ' ' + additionalArgs - - return exec(cmd, { - cwd: baseDir - }, done) - } - - if (command === 'run') { - this.runBackgroundProcess(['start', '--log-level', 'warn', configFile]) - .then(() => { - const cmd = runtimePath + ' run ' + configFile + ' ' + additionalArgs - - setTimeout(() => { - exec(cmd, { - cwd: baseDir - }, (error, stdout, stderr) => { - if (error) { - this.lastRun.error = error - } - this.lastRun.stdout = stdout - this.lastRun.stderr = stderr - callback() - }) - }, 1000) - }) - .catch((error) => callback(error)) - } else { - executor((error, stdout, stderr) => { - if (error) { - this.lastRun.error = error - } - this.lastRun.stdout = stdout - this.lastRun.stderr = stderr - callback() - }) - } + const cmd = `${this.karmaExecutable} ${command} --log-level ${level} ${this.configFile} ${additionalArgs}` + exec(cmd, { cwd: this.workDir }, (error, stdout, stderr) => { + this.lastRun.error = error + this.lastRun.stdout = stdout.toString() + this.lastRun.stderr = stderr.toString() + callback() + }) } Given('a default configuration', function () { @@ -83,6 +50,10 @@ When('I start a server in background', async function () { await this.runBackgroundProcess(['start', '--log-level', 'debug', this.configFile]) }) +When('I wait until server output contains:', async function (expectedOutput) { + await waitForCondition(() => this.backgroundProcess.stdout.includes(expectedOutput)) +}) + defineParameterType({ name: 'command', regexp: /run|start|init|stop/ @@ -105,7 +76,7 @@ Then(/^it passes with(:? (no\sdebug|like|regexp))?:$/, { timeout: 10 * 1000 }, f const noDebug = mode === 'no debug' const like = mode === 'like' const regexp = mode === 'regexp' - let actualOutput = this.lastRun.stdout.toString() + let actualOutput = this.lastRun.stdout let lines if (noDebug) { @@ -132,9 +103,9 @@ Then(/^it passes with(:? (no\sdebug|like|regexp))?:$/, { timeout: 10 * 1000 }, f }) Then('it fails with:', function (expectedOutput, callback) { - const actualOutput = this.lastRun.stdout.toString() + const actualOutput = this.lastRun.stdout const actualError = this.lastRun.error - const actualStderr = this.lastRun.stderr.toString() + const actualStderr = this.lastRun.stderr if (actualOutput.match(expectedOutput)) { return callback() @@ -146,9 +117,10 @@ Then('it fails with:', function (expectedOutput, callback) { }) Then('it fails with like:', function (expectedOutput, callback) { - const actualOutput = this.lastRun.stdout.toString() + const actualOutput = this.lastRun.stdout const actualError = this.lastRun.error - const actualStderr = this.lastRun.stderr.toString() + const actualStderr = this.lastRun.stderr + if (actualOutput.match(new RegExp(expectedOutput))) { return callback() } diff --git a/test/e2e/step_definitions/utils.js b/test/e2e/step_definitions/utils.js new file mode 100644 index 000000000..5dacbb470 --- /dev/null +++ b/test/e2e/step_definitions/utils.js @@ -0,0 +1,15 @@ +const { promisify } = require('util') + +const sleep = promisify(setTimeout) + +module.exports.waitForCondition = async (evaluateCondition, timeout = 1000) => { + let remainingTime = timeout + while (!evaluateCondition()) { + if (remainingTime > 0) { + await sleep(50) + remainingTime -= 50 + } else { + throw new Error(`Condition not fulfilled, waited ${timeout}ms`) + } + } +}