Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --parallel, --bail and --grep params to the test task #2359

Merged
merged 26 commits into from
Feb 23, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b97808f
Upgrade mocha to latest
fvictorio Feb 9, 2022
de16fcc
Add --parallel flag
fvictorio Feb 9, 2022
f498fc7
Fix autocomplete test
fvictorio Feb 9, 2022
ee68191
Run tests in parallel in e2e tests
fvictorio Feb 15, 2022
368c8bf
Add --bail and --grep params to test task
fvictorio Feb 15, 2022
c972d67
Add docs on running tests in parallel
fvictorio Feb 15, 2022
983f554
Merge branch 'master' into parallel-tests
fvictorio Feb 15, 2022
345ebab
Create hip-planes-invent.md
fvictorio Feb 15, 2022
ac001a4
Fix autocomplete tests
fvictorio Feb 15, 2022
30c1b7d
Update docs/guides/waffle-testing.md
fvictorio Feb 18, 2022
057dcdf
Update docs/guides/waffle-testing.md
fvictorio Feb 18, 2022
fe479e0
Improve explanation about potential timeouts
fvictorio Feb 18, 2022
b399960
Update packages/hardhat-core/src/builtin-tasks/test.ts
fvictorio Feb 18, 2022
7feb7f3
Update packages/hardhat-core/src/builtin-tasks/test.ts
fvictorio Feb 18, 2022
19df511
Fix linter
fvictorio Feb 18, 2022
bf6417e
Move parallel tests docs to their own guide
fvictorio Feb 18, 2022
60def3a
Force type imports to be at the beginning
fvictorio Feb 18, 2022
b74ee2e
Merge branch 'master' into parallel-tests
fvictorio Feb 18, 2022
84b070c
Add tests for test task
fvictorio Feb 18, 2022
3917ebe
Fix issue with false flags overriding mocha config
fvictorio Feb 18, 2022
3047a83
Fix linter
fvictorio Feb 18, 2022
8ba2070
Fix autocomplete test
fvictorio Feb 21, 2022
36411fd
Change how parallel mode is tested
fvictorio Feb 21, 2022
2aa70d4
Clarify how the HRE is shared in parallel tests doc
fvictorio Feb 21, 2022
7e8208a
Make SourceReference serializable
fvictorio Feb 22, 2022
7a6d522
Merge branch 'master' into parallel-tests
fvictorio Feb 22, 2022
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
7 changes: 7 additions & 0 deletions .changeset/hip-planes-invent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"hardhat": minor
---

The `test` task now supports a `--parallel` flag to run tests in parallel. There are also two other new flags: `--bail`, to stop the execution after the first test failure, and `--grep`, to filter which tests should be run.

To support running tests in parallel, the version of `mocha` used by Hardhat was upgraded to its latest version. This should be a mostly backward-compatible change, but there could be some edge cases where this breaks existing tests.
17 changes: 17 additions & 0 deletions docs/guides/waffle-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ expect(await greeter.greet()).to.equal("Hola, mundo!");

We can modify the state of a contract in the same way we read from it. Calling `setGreeting` will set a new greeting message. After the `Promise` is resolved, we perform another assertion to verify that the greeting change took effect.

### Running tests in parallel
Copy link
Member

Choose a reason for hiding this comment

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

I'd move this to its own guide, to make it more visible.

Also, this is not a waffle thing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.


You can run your tests in parallel by using the `--parallel` flag:

```
$ npx hardhat test --parallel
```

Most of the time, running your tests serially or in parallel should produce the same results, but there are some scenarios where tests run in parallel will behave differently:

- In serial mode, all the test files share the same instance of the [Hardhat Runtime Environment](/advanced/hardhat-runtime-environment.html), but in parallel mode each test file will have its own fresh instance. For example, if one test file deploys a contract, then that contract won't exist in the other test files.
fvictorio marked this conversation as resolved.
Show resolved Hide resolved
- The `.only` modifier doesn't work in parallel mode. You can use [`--grep`](https://mochajs.org/#-grep-regexp-g-regexp) to run specific tests.
fvictorio marked this conversation as resolved.
Show resolved Hide resolved
- The duration of individual tests might be different, because parallel mode uses more system resources. There's a chance that some tests start timing out for that reason. You can increase the tests timeout if you run into this problem.
fvictorio marked this conversation as resolved.
Show resolved Hide resolved
- The order in which tests are executed is non-deterministic.

There are some other limitations related to parallel mode. You can read more about them in [Mocha's docs](https://mochajs.org/#parallel-tests). And if you are running into some issue when using parallel mode, you can check their [Troubleshooting parallel mode](https://mochajs.org/#troubleshooting-parallel-mode) section.

### Testing from a different account

If you need to send a transaction from an account other than the default one, you can use the `connect()` method provided by Ethers.js.
Expand Down
4 changes: 2 additions & 2 deletions packages/e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"dependencies": {
"@types/chai": "^4.2.0",
"@types/fs-extra": "^5.1.0",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@types/shelljs": "^0.8.6",
"@typescript-eslint/eslint-plugin": "4.29.2",
Expand All @@ -32,7 +32,7 @@
"eslint-plugin-import": "2.24.1",
"eslint-plugin-prettier": "3.4.0",
"fs-extra": "^7.0.1",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
"shelljs": "^0.8.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
describe("simple", () => {
it("should pass", () => {});
});
21 changes: 20 additions & 1 deletion packages/e2e/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe("e2e tests", function () {
// check stdout

// check we get passing runs
assert.match(stdout, /1 passing/);
assert.match(stdout, /2 passing/);
// check we get no runs without tests
assert.notMatch(
stdout,
Expand All @@ -66,6 +66,25 @@ describe("e2e tests", function () {
const { code: hhCleanCode2 } = shell.exec(`${hardhatBinary} clean`);
assert.equal(hhCleanCode2, 0);
});

it("should run tests in parallel", function () {
// hh clean
const { code: hhCleanCode1 } = shell.exec(`${hardhatBinary} clean`);
assert.equal(hhCleanCode1, 0);

// hh test --parallel
const { code: hhCompileCode, stdout } = shell.exec(
`${hardhatBinary} test --parallel`
);
assert.equal(hhCompileCode, 0);

// check we get passing runs
assert.match(stdout, /2 passing/);

// hh clean
const { code: hhCleanCode2 } = shell.exec(`${hardhatBinary} clean`);
assert.equal(hhCleanCode2, 0);
});
});

describe("sample projects", function () {
Expand Down
6 changes: 3 additions & 3 deletions packages/hardhat-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@types/fs-extra": "^5.1.0",
"@types/glob": "^7.1.1",
"@types/lodash": "^4.14.123",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@types/node-fetch": "^2.3.7",
"@types/qs": "^6.5.3",
Expand All @@ -81,7 +81,7 @@
"eslint-plugin-import": "2.24.1",
"eslint-plugin-prettier": "3.4.0",
"ethers": "^5.0.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"proxy": "^1.0.2",
"rimraf": "^3.0.2",
Expand Down Expand Up @@ -124,7 +124,7 @@
"lodash": "^4.17.11",
"merkle-patricia-tree": "^4.2.2",
"mnemonist": "^0.38.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"node-fetch": "^2.6.0",
"qs": "^6.7.0",
"raw-body": "^2.4.1",
Expand Down
68 changes: 58 additions & 10 deletions packages/hardhat-core/src/builtin-tasks/test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import chalk from "chalk";
import type { MochaOptions } from "mocha";
alcuadrado marked this conversation as resolved.
Show resolved Hide resolved
import path from "path";

import { HARDHAT_NETWORK_NAME } from "../internal/constants";
Expand Down Expand Up @@ -43,24 +44,59 @@ subtask(TASK_TEST_GET_TEST_FILES)
subtask(TASK_TEST_SETUP_TEST_ENVIRONMENT, async () => {});

subtask(TASK_TEST_RUN_MOCHA_TESTS)
.addFlag("parallel", "Run tests in parallel")
.addFlag("bail", "Stop running tests after the first test failure")
.addOptionalParam("grep", "Only run tests matching the given regexp")
fvictorio marked this conversation as resolved.
Show resolved Hide resolved
.addOptionalVariadicPositionalParam(
"testFiles",
"An optional list of files to test",
[]
)
.setAction(async ({ testFiles }: { testFiles: string[] }, { config }) => {
const { default: Mocha } = await import("mocha");
const mocha = new Mocha(config.mocha);
testFiles.forEach((file) => mocha.addFile(file));
.setAction(
async (
{
bail,
parallel,
testFiles,
grep,
}: {
bail: boolean;
parallel: boolean;
testFiles: string[];
grep?: string;
},
{ config }
) => {
const { default: Mocha } = await import("mocha");

const testFailures = await new Promise<number>((resolve) => {
mocha.run(resolve);
});
const mochaConfig: MochaOptions = {
...config.mocha,
bail,
grep,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should/do we allow these to be configured in config.mocha as well? If so, this would overwrite them (i.e. if they were set in config.mocha but not passed as params to the subtask).

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, I hadn't noticed that, thanks for pointing it out. I actually think that would be the correct behavior though? Normally CLI flags override what's in the config (for example, that's what Prettier does by default). But it's good to know that this is the case. I will add a comment explaining that this is intentional.

Copy link
Member Author

Choose a reason for hiding this comment

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

Wait I see what you mean. For the grep flag this works correctly, but bail has a default value, and so it will always override whatever is in the config. I'll fix this, thank you.

Copy link
Member

Choose a reason for hiding this comment

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

Great catch! I was also tricked by this

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

};

mocha.dispose();
if (parallel) {
mochaConfig.parallel = true;

return testFailures;
});
const mochaRequire = mochaConfig.require ?? [];
if (!mochaRequire.includes("hardhat/register")) {
mochaRequire.push("hardhat/register");
}
mochaConfig.require = mochaRequire;
}

const mocha = new Mocha(mochaConfig);
testFiles.forEach((file) => mocha.addFile(file));

const testFailures = await new Promise<number>((resolve) => {
mocha.run(resolve);
});

mocha.dispose();

return testFailures;
}
);

subtask(TASK_TEST_RUN_SHOW_FORK_RECOMMENDATIONS).setAction(
async (_, { config, network }) => {
Expand All @@ -80,14 +116,23 @@ task(TASK_TEST, "Runs mocha tests")
[]
)
.addFlag("noCompile", "Don't compile before running this task")
.addFlag("parallel", "Run tests in parallel")
.addFlag("bail", "Stop running tests after the first test failure")
.addOptionalParam("grep", "Only run tests matching the given regexp")
fvictorio marked this conversation as resolved.
Show resolved Hide resolved
.setAction(
async (
{
testFiles,
noCompile,
parallel,
bail,
grep,
}: {
testFiles: string[];
noCompile: boolean;
parallel: boolean;
bail: boolean;
grep?: string;
},
{ run, network }
) => {
Expand All @@ -103,6 +148,9 @@ task(TASK_TEST, "Runs mocha tests")

const testFailures = await run(TASK_TEST_RUN_MOCHA_TESTS, {
testFiles: files,
parallel,
bail,
grep,
});

if (network.name === HARDHAT_NETWORK_NAME) {
Expand Down
12 changes: 12 additions & 0 deletions packages/hardhat-core/test/internal/cli/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,18 @@ describe("autocomplete", function () {
description: "Don't compile before running this task",
name: "--no-compile",
},
{
description: "Run tests in parallel",
name: "--parallel",
},
{
description: "Stop running tests after the first test failure",
name: "--bail",
},
{
description: "Only run tests matching the given regexp",
name: "--grep",
},
]);
});

Expand Down
8 changes: 4 additions & 4 deletions packages/hardhat-docker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,26 @@
"@types/chai": "^4.2.0",
"@types/dockerode": "^2.5.19",
"@types/fs-extra": "^5.1.0",
"@types/mocha": "^9.0.0",
"@types/node-fetch": "^2.3.7",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@types/node-fetch": "^2.3.7",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
"chai": "^4.2.0",
"eslint": "^7.29.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-import": "2.24.1",
"eslint-plugin-prettier": "3.4.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
"ts-node": "^8.1.0",
"typescript": "~4.5.2"
},
"peerDependencies": {},
"dependencies": {
"fs-extra": "^7.0.1",
"dockerode": "^2.5.8",
"fs-extra": "^7.0.1",
"node-fetch": "^2.6.0"
}
}
4 changes: 2 additions & 2 deletions packages/hardhat-ethers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
],
"devDependencies": {
"@types/chai": "^4.2.0",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
Expand All @@ -49,7 +49,7 @@
"eslint-plugin-prettier": "3.4.0",
"ethers": "^5.0.0",
"hardhat": "^2.0.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
"ts-node": "^8.1.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/hardhat-etherscan/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
"@types/cbor": "^5.0.1",
"@types/chai": "^4.2.0",
"@types/fs-extra": "^5.1.0",
"@types/mocha": "^9.0.0",
"@types/node-fetch": "^2.3.7",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@types/node-fetch": "^2.3.7",
"@types/semver": "^6.0.2",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
Expand All @@ -61,7 +61,7 @@
"eslint-plugin-prettier": "3.4.0",
"ethers": "^5.0.8",
"hardhat": "^2.0.4",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"nock": "^13.0.5",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-ganache/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@types/chai": "^4.2.0",
"@types/debug": "^4.1.4",
"@types/fs-extra": "^5.1.0",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
Expand All @@ -50,7 +50,7 @@
"eslint-plugin-import": "2.24.1",
"eslint-plugin-prettier": "3.4.0",
"hardhat": "^2.0.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
"ts-interface-builder": "^0.2.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-shorthand/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"devDependencies": {
"@types/chai": "^4.2.0",
"@types/fs-extra": "^5.1.0",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
Expand All @@ -44,7 +44,7 @@
"eslint-plugin-import": "2.24.1",
"eslint-plugin-prettier": "3.4.0",
"hardhat": "^2.0.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
"ts-node": "^8.1.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-solhint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"devDependencies": {
"@types/chai": "^4.2.0",
"@types/fs-extra": "^5.1.0",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
Expand All @@ -49,7 +49,7 @@
"eslint-plugin-prettier": "3.4.0",
"fs-extra": "^7.0.1",
"hardhat": "^2.0.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
"ts-node": "^8.1.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/hardhat-solpp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"devDependencies": {
"@types/chai": "^4.2.0",
"@types/fs-extra": "^5.1.0",
"@types/mocha": "^9.0.0",
"@types/mocha": "^9.1.0",
"@types/node": "^12.0.0",
"@typescript-eslint/eslint-plugin": "4.29.2",
"@typescript-eslint/parser": "4.29.2",
Expand All @@ -49,7 +49,7 @@
"eslint-plugin-import": "2.24.1",
"eslint-plugin-prettier": "3.4.0",
"hardhat": "^2.0.0",
"mocha": "^7.2.0",
"mocha": "^9.2.0",
"prettier": "2.4.1",
"rimraf": "^3.0.2",
"ts-node": "^8.1.0",
Expand Down
Loading