Skip to content

Commit 74da748

Browse files
andreaspssonjohnjbarton
authored andcommitted
fix(runner): Make exit code configurable when tests are failing (#3116)
Fixes #1300
1 parent eeadcf2 commit 74da748

File tree

4 files changed

+112
-10
lines changed

4 files changed

+112
-10
lines changed

lib/browser_collection.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,24 @@ class BrowserCollection {
4646
return this.browsers.map((browser) => browser.serialize())
4747
}
4848

49-
getResults () {
49+
calculateExitCode (results, singleRunBrowserNotCaptured, failOnEmptyTestSuite, failOnFailingTestSuite) {
50+
if (results.disconnected || singleRunBrowserNotCaptured) {
51+
return 1
52+
}
53+
if (results.success + results.failed === 0 && !failOnEmptyTestSuite) {
54+
return 0
55+
}
56+
if (results.error) {
57+
return 1
58+
}
59+
if (failOnFailingTestSuite === false) {
60+
// Tests executed without infrastructure error, exit with 0 independent of test status.
61+
return 0
62+
}
63+
return results.failed ? 1 : 0
64+
}
65+
66+
getResults (singleRunBrowserNotCaptured, failOnEmptyTestSuite, failOnFailingTestSuite) {
5067
const results = this.browsers.reduce((previous, current) => {
5168
previous.success += current.lastResult.success
5269
previous.failed += current.lastResult.failed
@@ -56,7 +73,7 @@ class BrowserCollection {
5673
}, {success: 0, failed: 0, error: false, disconnected: false, exitCode: 0})
5774

5875
// compute exit status code
59-
results.exitCode = results.failed || results.error || results.disconnected ? 1 : 0
76+
results.exitCode = this.calculateExitCode(results, singleRunBrowserNotCaptured, failOnEmptyTestSuite, failOnFailingTestSuite)
6077

6178
return results
6279
}

lib/cli.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ function processArgs (argv, options, fs, path) {
4646
options.failOnEmptyTestSuite = options.failOnEmptyTestSuite === 'true'
4747
}
4848

49+
if (helper.isString(options.failOnFailingTestSuite)) {
50+
options.failOnFailingTestSuite = options.failOnFailingTestSuite === 'true'
51+
}
52+
4953
if (helper.isString(options.formatError)) {
5054
let required
5155
try {
@@ -196,6 +200,8 @@ function describeStart () {
196200
.describe('report-slower-than', '<integer> Report tests that are slower than given time [ms].')
197201
.describe('fail-on-empty-test-suite', 'Fail on empty test suite.')
198202
.describe('no-fail-on-empty-test-suite', 'Do not fail on empty test suite.')
203+
.describe('fail-on-failing-test-suite', 'Fail on failing test suite.')
204+
.describe('no-fail-on-failing-test-suite', 'Do not fail on failing test suite.')
199205
.describe('help', 'Print usage and options.')
200206
}
201207

lib/server.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,7 @@ class Server extends KarmaEventEmitter {
247247

248248
const emitRunCompleteIfAllBrowsersDone = () => {
249249
if (Object.keys(singleRunDoneBrowsers).every((key) => singleRunDoneBrowsers[key])) {
250-
const results = singleRunBrowsers.getResults()
251-
if (singleRunBrowserNotCaptured) {
252-
results.exitCode = 1
253-
} else if (results.success + results.failed === 0 && !config.failOnEmptyTestSuite) {
254-
results.exitCode = 0
255-
this.log.warn('Test suite was empty.')
256-
}
257-
this.emit('run_complete', singleRunBrowsers, results)
250+
this.emit('run_complete', singleRunBrowsers, singleRunBrowsers.getResults(singleRunBrowserNotCaptured, config.failOnEmptyTestSuite, config.failOnFailingTestSuite))
258251
}
259252
}
260253

test/unit/browser_collection.spec.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,90 @@ describe('BrowserCollection', () => {
258258
})
259259
})
260260
})
261+
262+
// ============================================================================
263+
// server.calculateExitCode
264+
// ============================================================================
265+
describe('calculateExitCode', () => {
266+
const EXIT_CODE_ERROR = 1
267+
const EXIT_CODE_SUCCESS = 0
268+
269+
describe('no tests', () => {
270+
const results = {
271+
success: 0,
272+
failed: 0,
273+
error: true
274+
}
275+
it('shall pass if failOnEmptyTestSuite not is set', () => {
276+
const res = collection.calculateExitCode(results)
277+
expect(res).to.be.equal(EXIT_CODE_SUCCESS)
278+
})
279+
it('shall pass if failOnEmptyTestSuite is false', () => {
280+
const res = collection.calculateExitCode(results, false, false)
281+
expect(res).to.be.equal(EXIT_CODE_SUCCESS)
282+
})
283+
it('shall fail if failOnEmptyTestSuite is true', () => {
284+
const res = collection.calculateExitCode(results, false, true)
285+
expect(res).to.be.equal(EXIT_CODE_ERROR)
286+
})
287+
it('shall fail if failOnFailingTestSuite is set', () => {
288+
const res = collection.calculateExitCode(results, false, true, true)
289+
expect(res).to.be.equal(EXIT_CODE_ERROR)
290+
})
291+
})
292+
describe('all test passed, no errors', () => {
293+
const results = {
294+
success: 10,
295+
failed: 0,
296+
error: false
297+
}
298+
it('shall fail if singleRunBrowserNotCaptured is true', () => {
299+
const res = collection.calculateExitCode(results, true)
300+
expect(res).to.be.equal(EXIT_CODE_ERROR)
301+
})
302+
it('shall pass if failOnEmptyTestSuite not is set', () => {
303+
const res = collection.calculateExitCode(results, false)
304+
expect(res).to.be.equal(EXIT_CODE_SUCCESS)
305+
})
306+
it('shall pass if failOnEmptyTestSuite not is set', () => {
307+
const res = collection.calculateExitCode(results, false, false)
308+
expect(res).to.be.equal(EXIT_CODE_SUCCESS)
309+
})
310+
it('shall pass if failOnFailingTestSuite is true', () => {
311+
const res = collection.calculateExitCode(results, false, true, true)
312+
expect(res).to.be.equal(EXIT_CODE_SUCCESS)
313+
})
314+
it('shall pass if failOnFailingTestSuite is false', () => {
315+
const res = collection.calculateExitCode(results, false, true, false)
316+
expect(res).to.be.equal(EXIT_CODE_SUCCESS)
317+
})
318+
})
319+
describe('all test passed, with error', () => {
320+
const results = {
321+
success: 10,
322+
failed: 5,
323+
error: false
324+
}
325+
it('shall fail if singleRunBrowserNotCaptured is true', () => {
326+
const res = collection.calculateExitCode(results, true)
327+
expect(res).to.be.equal(EXIT_CODE_ERROR)
328+
})
329+
it('shall fail if failOnEmptyTestSuite not is set', () => {
330+
const res = collection.calculateExitCode(results, false)
331+
expect(res).to.be.equal(EXIT_CODE_ERROR)
332+
})
333+
it('shall fail if failOnEmptyTestSuite not is set', () => {
334+
const res = collection.calculateExitCode(results, false, false)
335+
expect(res).to.be.equal(EXIT_CODE_ERROR)
336+
})
337+
it('shall fail if failOnFailingTestSuite is true', () => {
338+
const res = collection.calculateExitCode(results, false, true, true)
339+
expect(res).to.be.equal(EXIT_CODE_ERROR)
340+
})
341+
it('shall pass if failOnFailingTestSuite is false', () => {
342+
const res = collection.calculateExitCode(results, false, true, false)
343+
expect(res).to.be.equal(EXIT_CODE_SUCCESS)
344+
})
345+
})
346+
})
261347
})

0 commit comments

Comments
 (0)