Testing is a critical part of the smart contract development process. However, tests can sometimes be slow, especially as your project grows. In this guide, we will explore various strategies to improve the speed of your Hardhat tests, along with sample code and best practices.
1. Use the Hardhat Network
When running tests, always use the Hardhat Network, which is optimized for speed and provides instant transaction confirmations. It can handle multiple transactions in a single block, making it faster than using a public test network.
Running Tests on the Hardhat Network
To run your tests on the Hardhat Network, simply execute:
npx hardhat test
2. Use `beforeEach` Wisely
The beforeEach
hook in Mocha is executed before each test case. If you have expensive setup operations, consider whether they need to run before every test or if they can be run once for multiple tests.
Example of Inefficient Use of `beforeEach`
describe("MyContract", function () {
let myContract;
beforeEach(async function () {
myContract = await MyContract.deploy(); // Deploying before each test
await myContract.deployed();
});
it("Test 1", async function () {
// Test logic
});
it("Test 2", async function () {
// Test logic
});
});
Improved Use of `before`
If the state does not need to be reset between tests, use the before
hook instead:
describe("MyContract", function () {
let myContract;
before(async function () {
myContract = await MyContract.deploy(); // Deploying once
await myContract.deployed();
});
it("Test 1", async function () {
// Test logic
});
it("Test 2", async function () {
// Test logic
});
});
3. Minimize State Changes
State changes in smart contracts are costly and can slow down tests. Minimize the number of state changes you make in your tests to improve speed.
Example of Excessive State Changes
it("should update state multiple times", async function () {
await myContract.setValue(1);
await myContract.setValue(2);
await myContract.setValue(3); // Multiple state changes
});
Optimized State Changes
Try to batch state changes when possible:
it("should update state once", async function () {
await myContract.batchUpdate([1, 2, 3]); // Single state change
});
4. Use `skip` and `only` Wisely
While developing, you can use the skip
and only
methods to focus on specific tests. This can significantly reduce the time spent running tests during development.
Example of Using `only`
it.only("should test specific functionality", async function () {
// This test will run, skipping all others
});
5. Parallel Testing with Mocha
Mocha supports parallel test execution, which can significantly speed up your testing process. You can enable parallel execution by using the beforeEach
0 flag when running your tests.
Running Tests in Parallel
beforeEach
1
Note that not all tests can run in parallel, especially if they modify shared state. Ensure your tests are independent before using this feature.
6. Optimize Gas Usage in Tests
Optimizing gas usage in your contracts can lead to faster tests. Use tools like the Hardhat Gas Reporter to identify gas-heavy functions and refactor them as needed.
Using Hardhat Gas Reporter
beforeEach
2
7. Use Mock Contracts
Mock contracts can be used to simulate the behavior of complex dependencies, allowing you to isolate the contract under test and speed up the testing process.
Example of Using Mock Contracts
beforeEach
3
Conclusion
Improving the speed of your Hardhat tests is essential for a smooth development experience. By utilizing the Hardhat Network, optimizing the use of hooks, minimizing state changes, leveraging parallel testing, and using mock contracts, you can significantly reduce the time it takes to run your tests. Implementing these strategies will not only enhance your productivity but also lead to a more efficient development workflow.