Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ runner.run(collection, {
// calls the `item` and `iteration` callbacks and does not run any further items (requests)
stopOnFailure: true,

// - gracefully halts on test failures only (not on errors).
// calls the `item` and `iteration` callbacks and does not run any further items (requests)
stopOnAssertionFailure: true,

// - abruptly halts the run on errors or test failures, and directly calls the `done` callback
abortOnFailure: true,

Expand Down
32 changes: 28 additions & 4 deletions lib/runner/extensions/event.command.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@
* execution of a script will stop executing any further scripts
* @param {Boolean} [payload.abortOnFailure] -
* @param {Boolean} [payload.stopOnFailure] -
* @param {Boolean} [payload.stopOnAssertionFailure] -
* @param {Function} next -
*
* @note - in order to raise trigger for the entire event, ensure your extension has registered the triggers
Expand All @@ -243,6 +244,7 @@
// @todo: find a better home for this option processing
abortOnFailure = payload.abortOnFailure,
stopOnFailure = payload.stopOnFailure,
stopOnAssertionFailure = payload.stopOnAssertionFailure,

packageResolver = _.get(this, 'options.script.packageResolver'),

Expand Down Expand Up @@ -318,7 +320,7 @@

// add event listener to trap all assertion events, but only if needed. to avoid needlessly accumulate
// stuff in memory.
(abortOnFailure || stopOnFailure) &&
(abortOnFailure || stopOnFailure || stopOnAssertionFailure) &&
this.host.on(EXECUTION_ASSERTION_EVENT_BASE + executionId, function (scriptCursor, assertions) {
_.forEach(assertions, function (assertion) {
assertion && !assertion.passed && assertionFailed.push(assertion.name);
Expand Down Expand Up @@ -581,8 +583,16 @@
});

// Get the failures. If there was an error running the script itself, that takes precedence
if (!err && (abortOnFailure || stopOnFailure)) {
err = postProcessContext(result, assertionFailed); // also use async assertions
// For stopOnAssertionFailure, we only create an error if there are assertion failures
// For stopOnFailure/abortOnFailure, we create error for any failures
if (!err && (abortOnFailure || stopOnFailure || stopOnAssertionFailure)) {
var assertionError = postProcessContext(result, assertionFailed);

// For stopOnAssertionFailure, only set err if it's an assertion failure
// For stopOnFailure/abortOnFailure, set err for any error
if (abortOnFailure || stopOnFailure || (stopOnAssertionFailure && assertionError)) {
err = assertionError;
}
}

// Ensure that we have SDK instances, not serialized plain objects.
Expand Down Expand Up @@ -642,7 +652,21 @@
}

// move to next script and pass on the results for accumulation
done(((stopOnScriptError || abortOnError || stopOnFailure) && err) ? err : null, _.assign({
// For stopOnAssertionFailure, only stop if the error is an assertion failure
var shouldStop = false;

Check failure on line 656 in lib/runner/extensions/event.command.js

View workflow job for this annotation

GitHub Actions / Lint

Combine this with the previous 'var' statement

if (err) {
var isAssertionFailure = err.name === ASSERTION_FAILURE ||

Check failure on line 659 in lib/runner/extensions/event.command.js

View workflow job for this annotation

GitHub Actions / Lint

Combine this with the previous 'var' statement
(err.error && err.error.name === ASSERTION_FAILURE);

if (stopOnScriptError || abortOnError || stopOnFailure) {
shouldStop = true;
} else if (stopOnAssertionFailure && isAssertionFailure) {

Check failure on line 664 in lib/runner/extensions/event.command.js

View workflow job for this annotation

GitHub Actions / Lint

Closing curly brace appears on the same line as the subsequent block
shouldStop = true;
}
}

done(shouldStop ? err : null, _.assign({
event,
script,
result
Expand Down
25 changes: 21 additions & 4 deletions lib/runner/extensions/item.command.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
// still not sure whether that is the right place for it to be.
abortOnFailure = this.options.abortOnFailure,
stopOnFailure = this.options.stopOnFailure,
stopOnAssertionFailure = this.options.stopOnAssertionFailure,
delay = _.get(this.options, 'delay.item'),

ctxTemplate;
Expand Down Expand Up @@ -155,10 +156,12 @@
// No need to include vaultSecrets here as runtime takes care of tracking internally
trackContext: ['globals', 'environment', 'collectionVariables'],
stopOnScriptError: stopOnError,
stopOnFailure: stopOnFailure
stopOnFailure: stopOnFailure,
stopOnAssertionFailure: stopOnAssertionFailure
}).done(function (prereqExecutions, prereqExecutionError, shouldSkipExecution) {
// if stop on error is marked and script executions had an error,
// do not proceed with more commands, instead we bail out
// Note: stopOnAssertionFailure doesn't stop on execution errors, only assertion failures
if ((stopOnError || stopOnFailure) && prereqExecutionError) {
this.triggers.item(null, coords, item); // @todo - should this trigger receive error?

Expand Down Expand Up @@ -239,7 +242,8 @@
trackContext: ['tests', 'globals', 'environment', 'collectionVariables'],
stopOnScriptError: stopOnError,
abortOnFailure: abortOnFailure,
stopOnFailure: stopOnFailure
stopOnFailure: stopOnFailure,
stopOnAssertionFailure: stopOnAssertionFailure
}).done(function (testExecutions, testExecutionError) {
var visualizerData = extractVisualizerData(prereqExecutions, testExecutions),
visualizerResult;
Expand Down Expand Up @@ -272,8 +276,21 @@
// @note request mutations are not persisted across iterations
item.request = originalRequest;

callback && callback.call(this, ((stopOnError || stopOnFailure) && testExecutionError) ?
testExecutionError : null, {
// Check if we should stop: stopOnError/stopOnFailure stop on any error,
// stopOnAssertionFailure only stops on assertion failures
var shouldStop = false;

Check failure on line 281 in lib/runner/extensions/item.command.js

View workflow job for this annotation

GitHub Actions / Lint

Combine this with the previous 'var' statement
if (testExecutionError) {

Check failure on line 282 in lib/runner/extensions/item.command.js

View workflow job for this annotation

GitHub Actions / Lint

Expected blank line before this statement
var isAssertionFailure = testExecutionError.name === 'AssertionFailure' ||

Check failure on line 283 in lib/runner/extensions/item.command.js

View workflow job for this annotation

GitHub Actions / Lint

Combine this with the previous 'var' statement
(testExecutionError.error && testExecutionError.error.name === 'AssertionFailure');

if (stopOnError || stopOnFailure) {
shouldStop = true;
} else if (stopOnAssertionFailure && isAssertionFailure) {

Check failure on line 288 in lib/runner/extensions/item.command.js

View workflow job for this annotation

GitHub Actions / Lint

Closing curly brace appears on the same line as the subsequent block
shouldStop = true;
}
}

callback && callback.call(this, shouldStop ? testExecutionError : null, {
prerequest: prereqExecutions,
request: request,
response: response,
Expand Down
17 changes: 14 additions & 3 deletions lib/runner/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@
* @param {Object} options.coords - Current coordinates
* @param {Object} options.executions - Execution results (prerequest and test)
* @param {Error} options.executionError - Any execution error
* @param {Object} options.runnerOptions - Runner options (disableSNR, stopOnFailure)
* @param {Object} options.runnerOptions - Runner options (disableSNR, stopOnFailure, stopOnAssertionFailure)
* @param {Object} options.snrHash - SNR lookup hash
* @param {Array} options.items - Collection items for SNR hash preparation
* @returns {Object} Processing result with nextCoords, seekingToStart, stopRunNow flags
Expand All @@ -343,7 +343,8 @@
nextCoords,
seekingToStart,
stopRunNow,
stopOnFailure = runnerOptions.stopOnFailure;
stopOnFailure = runnerOptions.stopOnFailure,
stopOnAssertionFailure = runnerOptions.stopOnAssertionFailure;

if (!executionError) {
// extract set next request
Expand Down Expand Up @@ -380,7 +381,17 @@
(snr.defined || executionError) && (nextCoords.position = nextCoords.length - 1);

// If we need to stop on a run, we set the stop flag to true.
(stopOnFailure && executionError) && (stopRunNow = true);
// stopOnFailure stops on any error, stopOnAssertionFailure only stops on assertion failures
if (executionError) {
var isAssertionFailure = executionError.name === 'AssertionFailure' ||

Check failure on line 386 in lib/runner/util.js

View workflow job for this annotation

GitHub Actions / Lint

Combine this with the previous 'var' statement
(executionError.error && executionError.error.name === 'AssertionFailure');

if (stopOnFailure) {
stopRunNow = true;
} else if (stopOnAssertionFailure && isAssertionFailure) {

Check failure on line 391 in lib/runner/util.js

View workflow job for this annotation

GitHub Actions / Lint

Closing curly brace appears on the same line as the subsequent block
stopRunNow = true;
}
}
}

// @todo - do this in unhacky way
Expand Down
Loading