Testing Guidelines
Ensuring the quality and security of smart contracts in Decentra projects requires rigorous testing. This page provides detailed guidelines on how to write and execute Foundry tests, along with a style guide to ensure consistency and comprehensiveness.
General Guidelines for Writing Foundry Tests
Setup and Teardown: Use a base test to initialize the state before each test and clean up after each test.
Coverage: Aim for 100% test coverage to ensure all parts of the code are tested.
Structure: Follow a consistent structure for all tests to maintain readability and organization.
Style Guide for Foundry Tests
1. Base Test:
The base test should set up the environment for the contracts and hold any state-setting logic and mocks. All other test contracts will inherit from this base test.
Example:
// BaseTest.sol
import "forge-std/Test.sol";
import "../src/MyContract.sol";
contract BaseTest is Test {
MyContract internal myContract;
function setUp() public virtual {
myContract = new MyContract();
// Additional setup logic, such as setting initial state or deploying mock contracts
}
}
2. Inheriting Base Test:
All other test contracts should inherit from the base test and implement their specific tests. This ensures consistency and reduces duplication.
Example:
3. Test Naming and Structure:
Tests should be ordered in the same way as the functions in the contract and should cover possible edge cases and security issues. Use descriptive names for test functions to clearly indicate their purpose.
Example:
4. Coverage:
Ensure that your tests cover 100% of the code. This includes all functions, branches, and lines. Use tools to measure test coverage and identify any untested parts of the code.
Writing Effective Tests
Unit Tests: Test individual functions in isolation to ensure they behave as expected.
Integration Tests: Test interactions between multiple functions or contracts to ensure they work together correctly.
Edge Cases: Test unusual or extreme inputs to ensure the contract handles them gracefully.
Revert Tests: Test that the contract correctly reverts in invalid scenarios using descriptive test names such as
test_RevertWhen_<condition>().Security Tests: Include tests for common security vulnerabilities, such as reentrancy, overflow/underflow, and unauthorized access.
Running Tests
To run the tests, use the Foundry frameworkβs command-line tools. Ensure that all tests pass before submitting your code.
Running All Tests:
Running a Specific Test:
Measuring Coverage:
Example Test File Structure
Optimization Note
The codebase and tests should be optimized to compile without the --via-ir flag. The Intermediate Representation (IR) compiler flag can increase the complexity and potentially introduce inefficiencies. Ensuring your code is compatible with standard compilation settings maintains optimal performance, simplifies the compilation process, and avoids unnecessary dependencies.
By following these testing guidelines and style guide, developers can ensure that their smart contracts are thoroughly tested, secure, and reliable. This contributes to the overall integrity and robustness of Decentra projects.