Skip to content
This repository was archived by the owner on Sep 21, 2022. It is now read-only.
Merged
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
5 changes: 5 additions & 0 deletions doc/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ Settings list:
specified, the fallen tests will not be relaunched (by default it's 0).

Note that the same test never be performed in the same browser session.

* `shouldRetry` — function which defines whether to make a retry. Should returns `Boolean` value. First argument is `data` which is the result of the test run, it's an Object with following fields:
* `attempt {Number}` number of retries performed for the test
* `retriesLeft {Number}` number of retries left
* `[equal] {Boolean}` notice that if the test fails with critical error equal can be absent

* `screenshotMode` — image capture mode. There are 3 allowed values for this option:
* `auto` (default). Mode will be obtained automatically.
Expand Down
22 changes: 17 additions & 5 deletions lib/runner/suite-runner/insistent-suite-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,27 @@ module.exports = class InsistentSuiteRunner extends SuiteRunner {
this._statesToRetry.forEach((state) => collection.enable(suite, {state, browser}));
}

_submitForRetry(e) {
const retriesLeft = this._config.retry - this._retriesPerformed;
if (retriesLeft <= 0) {
_shouldRetry(data) {
if (typeof this._config.shouldRetry === 'function') {
return this._config.shouldRetry(data);
}

return data.retriesLeft > 0;
}

_submitForRetry(data) {
Object.assign(data, {
attempt: this._retriesPerformed,

@miripiruni miripiruni Feb 7, 2018

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Честно, я не понял где это используется… Возможно, это поле можно убрать?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

retriesMade/retriesLeft будет симметричнее.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это обратно несовместимое изменение, не надо этого делать

retriesLeft: this._config.retry - this._retriesPerformed
});

if (!this._shouldRetry(data)) {
return false;
}

this._statesToRetry = this._statesToRetry.concat(e.state.name);
this._statesToRetry = this._statesToRetry.concat(data.state.name);

this._emit(Events.RETRY, _.extend(e, {attempt: this._retriesPerformed, retriesLeft}));
this._emit(Events.RETRY, data);
return true;
}
};
63 changes: 63 additions & 0 deletions test/unit/runner/suite-runner/insistent-suite-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,37 @@ describe('runner/suite-runner/insistent-suite-runner', () => {
assert.calledOnce(RegularSuiteRunner.prototype.run);
});
});

it('should not retry if config shouldRetry() told so', () => {
stubWrappedRun_((runner) => runner.emit(Events.ERROR, {state: makeStateStub()}));
const config = mkConfigStub_({
retry: 100,
shouldRetry: () => false
});

return mkInsistentRunner_({config})
.run()
.then(() => assert(RegularSuiteRunner.prototype.run.calledOnce));
});

it('shouldRetry() should have proper argument', () => {
stubWrappedRun_((runner) => runner.emit(Events.ERROR, {state: makeStateStub()}));
const rule = sandbox.spy();
const config = mkConfigStub_({
retry: 1,
shouldRetry: rule
});

return mkInsistentRunner_({config})
.run()
.then(() => {
const firstCallArgs = rule.firstCall.args;
const arg = firstCallArgs[0];
assert.equal(firstCallArgs.length, 1, 'shouldRetry() expect one argument');
assert.typeOf(arg.retriesLeft, 'number', 'No "retriesLeft" property in shouldRetry argument');
assert.typeOf(arg.attempt, 'number', 'No "attempt" property in shouldRetry argument');
});
});
});

describe('on TEST_RESULT without diff', () => {
Expand Down Expand Up @@ -387,6 +418,38 @@ describe('runner/suite-runner/insistent-suite-runner', () => {
assert.calledOnce(RegularSuiteRunner.prototype.run);
});
});

it('should not retry if config shouldRetry() told so', () => {
stubWrappedRun_((runner) => runner.emit(Events.TEST_RESULT, {state: makeStateStub()}));
const config = mkConfigStub_({
retry: 100,
shouldRetry: () => false
});

return mkInsistentRunner_({config})
.run()
.then(() => assert(RegularSuiteRunner.prototype.run.calledOnce));
});

it('shouldRetry() should have proper argument', () => {
stubWrappedRun_((runner) => runner.emit(Events.TEST_RESULT, {equal: false, state: makeStateStub()}));
const rule = sandbox.spy();
const config = mkConfigStub_({
retry: 1,
shouldRetry: rule
});

return mkInsistentRunner_({config})
.run()
.then(() => {
const firstCallArgs = rule.firstCall.args;
const arg = firstCallArgs[0];
assert.equal(firstCallArgs.length, 1, 'shouldRetry() expect one argument');
assert.typeOf(arg.retriesLeft, 'number', 'No "retriesLeft" property in shouldRetry argument');
assert.typeOf(arg.attempt, 'number', 'No "attempt" property in shouldRetry argument');
assert.typeOf(arg.equal, 'boolean', 'No "equal" property in shouldRetry argument');
});
});
});

it('should retry only failed states', () => {
Expand Down