How to Test Smart Contracts in Solidity: Simple Guide
To test a
Solidity smart contract, write test scripts using frameworks like Hardhat or Truffle that deploy the contract and check its functions. Use JavaScript or TypeScript tests with assertions to verify expected behavior automatically.Syntax
Testing a Solidity smart contract typically involves these steps:
- Deploy the contract: Create a fresh instance for each test.
- Call contract functions: Interact with the contract methods.
- Assert expected results: Check if outputs or state changes match expectations.
Example test structure in JavaScript with Hardhat:
javascript
describe('ContractName', function () { let contract; beforeEach(async function () { const ContractFactory = await ethers.getContractFactory('ContractName'); contract = await ContractFactory.deploy(); await contract.deployed(); }); it('should do something expected', async function () { const result = await contract.someFunction(); expect(result).to.equal(expectedValue); }); });
Example
This example shows how to test a simple Solidity contract that stores and retrieves a number using Hardhat and Mocha testing framework.
solidity and javascript
// Solidity contract: SimpleStorage.sol pragma solidity ^0.8.0; contract SimpleStorage { uint256 private storedNumber; function set(uint256 num) public { storedNumber = num; } function get() public view returns (uint256) { return storedNumber; } } // JavaScript test: test/SimpleStorage.js const { expect } = require('chai'); describe('SimpleStorage', function () { let simpleStorage; beforeEach(async function () { const SimpleStorage = await ethers.getContractFactory('SimpleStorage'); simpleStorage = await SimpleStorage.deploy(); await simpleStorage.deployed(); }); it('should return 0 initially', async function () { expect(await simpleStorage.get()).to.equal(0); }); it('should store and return the correct number', async function () { await simpleStorage.set(42); expect(await simpleStorage.get()).to.equal(42); }); });
Output
SimpleStorage
โ should return 0 initially
โ should store and return the correct number
2 passing (XXms)
Common Pitfalls
Common mistakes when testing smart contracts include:
- Not deploying a fresh contract instance before each test, causing state to leak between tests.
- Forgetting to
awaitasynchronous calls, leading to false positives or errors. - Not using assertions to check results, so tests pass without verifying behavior.
- Ignoring revert or failure cases by not testing for expected errors.
Example of a wrong test missing await:
javascript
// Wrong test (missing await) it('should store number', function () { simpleStorage.set(10); // missing await expect(simpleStorage.get()).to.equal(10); // fails because set not completed }); // Correct test it('should store number', async function () { await simpleStorage.set(10); expect(await simpleStorage.get()).to.equal(10); });
Quick Reference
Tips for effective smart contract testing:
- Use
beforeEachto deploy a new contract instance for isolation. - Always
awaitcontract calls and transactions. - Test both success and failure scenarios.
- Use assertion libraries like
chaifor clear checks. - Run tests frequently during development to catch bugs early.
Key Takeaways
Always deploy a fresh contract instance before each test to avoid state conflicts.
Use async/await to handle contract calls and transactions properly.
Write assertions to verify contract behavior and expected results.
Test both normal and error cases to ensure contract robustness.
Use frameworks like Hardhat or Truffle for easy and automated testing.