Skip to content

Commit e6772cf

Browse files
committed
implement repeats
Refs: Re-run a test multiple times #2332
1 parent f4d4ad2 commit e6772cf

35 files changed

+682
-1
lines changed

docs/index.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,31 @@ describe("retries", function () {
707707
});
708708
```
709709

710+
## Repeat Tests
711+
712+
Tests can also be repeated when they pass. This feature can be used to test for leaks and proper tear-down procedures. In this case a test is considered to be successful only if all the runs are successful.
713+
714+
This feature does re-run a passed test and its corresponding `beforeEach/afterEach` hooks, but not `before/after` hooks.
715+
716+
If using both `repeat` and `retries`, the test will be run `repeat` times tolerating up to `retries` failures in total.
717+
718+
```js
719+
describe('repeat', function () {
720+
// Repeat all tests in this suite 4 times
721+
this.repeats(4);
722+
723+
beforeEach(function () {
724+
browser.get('http://www.yahoo.com');
725+
});
726+
727+
it('should use proper tear-down', function () {
728+
// Specify this test to only retry up to 2 times
729+
this.repeats(2);
730+
expect($('.foo').isDisplayed()).to.eventually.be.true;
731+
});
732+
});
733+
```
734+
710735
## Dynamically Generating Tests
711736

712737
Given Mocha's use of function expressions to define suites and test cases, it's straightforward to generate your tests dynamically. No special syntax is required — plain ol' JavaScript can be used to achieve functionality similar to "parameterized" tests, which you may have seen in other frameworks.
@@ -2218,6 +2243,7 @@ mocha.setup({
22182243
forbidPending: true,
22192244
global: ['MyLib'],
22202245
retries: 3,
2246+
repeats: 1,
22212247
rootHooks: { beforeEach(done) { ... done();} },
22222248
slow: '100',
22232249
timeout: '2000',

example/config/.mocharc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ module.exports = {
3636
"reporter-option": ["foo=bar", "baz=quux"], // array, not object
3737
require: "@babel/register",
3838
retries: 1,
39+
repeats: 1,
3940
slow: "75",
4041
sort: false,
4142
spec: ["test/**/*.spec.js"], // the positional arguments!

example/config/.mocharc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ reporter-option: # array, not object
4040
- "baz=quux"
4141
require: "@babel/register"
4242
retries: 1
43+
repeats: 1
4344
slow: "75"
4445
sort: false
4546
spec:

lib/cli/run-option-metadata.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const TYPES = (exports.types = {
5151
"sort",
5252
"watch",
5353
],
54-
number: ["retries", "jobs"],
54+
number: ["retries", "repeats", "jobs"],
5555
string: [
5656
"config",
5757
"fgrep",

lib/cli/run.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ exports.builder = (yargs) =>
247247
description: "Retry failed tests this many times",
248248
group: GROUPS.RULES,
249249
},
250+
repeats: {
251+
description: 'Repeat passed tests this many times',
252+
group: GROUPS.RULES
253+
},
250254
slow: {
251255
default: defaults.slow,
252256
description: 'Specify "slow" test threshold (in milliseconds)',

lib/context.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,18 @@ Context.prototype.retries = function (n) {
8989
this.runnable().retries(n);
9090
return this;
9191
};
92+
93+
/**
94+
* Set or get a number of repeats on passed tests
95+
*
96+
* @private
97+
* @param {number} n
98+
* @return {Context} self
99+
*/
100+
Context.prototype.repeats = function (n) {
101+
if (!arguments.length) {
102+
return this.runnable().repeats();
103+
}
104+
this.runnable().repeats(n);
105+
return this;
106+
};

lib/hook.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Hook.prototype.error = function (err) {
6363
Hook.prototype.serialize = function serialize() {
6464
return {
6565
$$currentRetry: this.currentRetry(),
66+
$$currentRepeat: this.currentRepeat(),
6667
$$fullTitle: this.fullTitle(),
6768
$$isPending: Boolean(this.isPending()),
6869
$$titlePath: this.titlePath(),

lib/mocha.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ function Mocha(options = {}) {
188188
this.retries(options.retries);
189189
}
190190

191+
if ("repeats" in options) {
192+
this.repeats(options.repeats);
193+
}
194+
191195
[
192196
"allowUncaught",
193197
"asyncOnly",
@@ -745,6 +749,25 @@ Mocha.prototype.retries = function (retry) {
745749
return this;
746750
};
747751

752+
/**
753+
* Sets the number of times to repeat passed tests.
754+
*
755+
* @public
756+
* @see [CLI option](../#-repeats-n)
757+
* @see [Repeat Tests](../#repeat-tests)
758+
* @param {number} repeats - Number of times to repeat passed tests.
759+
* @return {Mocha} this
760+
* @chainable
761+
* @example
762+
*
763+
* // Allow any passed test to be repeated multiple times
764+
* mocha.repeats(1);
765+
*/
766+
Mocha.prototype.repeats = function (repeats) {
767+
this.suite.repeats(repeats);
768+
return this;
769+
};
770+
748771
/**
749772
* Sets slowness threshold value.
750773
*

lib/reporters/json-stream.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ function clean(test) {
8686
file: test.file,
8787
duration: test.duration,
8888
currentRetry: test.currentRetry(),
89+
currentRepeat: test.currentRepeat(),
8990
speed: test.speed,
9091
};
9192
}

lib/reporters/json.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ function clean(test) {
120120
file: test.file,
121121
duration: test.duration,
122122
currentRetry: test.currentRetry(),
123+
currentRepeat: test.currentRepeat(),
123124
speed: test.speed,
124125
err: cleanCycles(err),
125126
};

0 commit comments

Comments
 (0)