// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.16;
import "forge-std/Test.sol";
import "../src/SampleContract.sol";
import "forge-std/console.sol";
// vm deployer address: 0xb4c79daB8f259C7Aee6E5b2Aa729821864227e84
abstract contract StateZero is Test {
SampleContract internal sampleContract;
address alice;
address bob;
function setUp() public virtual {
sampleContract = new SampleContract();
alice = address(0x1);
bob = address(0x2);
vm.label(alice, "alice");
vm.label(bob, "bob");
}
}
contract StateZeroTest is StateZero {
function testChangeStateOne() public {}
function testChangStateOneReverts() public {
vm.expectRevert(bytes("revert message"));
// call function that is intended to revert here
}
function testChangStateOneEmitsEvent() public {
vm.expectEmit(true, true, true, true);
// 1. emit the event with expected values
// 2. call function that is intended to emit the event
}
}
abstract contract StateOne is StateZero {
function setUp() public virtual override {
// run initial set-up function from StateZero
super.setUp();
// function that changes state from zero to one
sampleContract.changeStateOne();
}
}
contract StateOneTest is StateOne {
function testChangeStateTwo() public {}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.16;
import "forge-std/console2.sol";
import "openzeppelin-contracts/contracts/access/Ownable.sol";
import "openzeppelin-contracts/contracts/utils/Counters.sol";
contract SampleContract {
// initialising new counter variable
using Counters for Counters.Counter;
Counters.Counter public someId;
....
}
Fuzz Testing
Fuzz testing is done by using a range of randomized possible inputs to test for edge cases, instead of just testing it with select inputs as in unit testing.
Foundry lets us do this natively.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "../src/Counter.sol";
contract CounterTest is Test {
Counter public counter;
function setUp() public {
counter = new Counter();
}
// Fuzz test for setNumber function
function testFuzz_SetNumber(uint256 x) public {
counter.setNumber(x);
assertEq(counter.number(), x);
}
// Fuzz test for multiple increment operations
function testFuzz_Increment(uint8 numberOfIncrements) public {
uint256 startingValue = counter.number();
for (uint i = 0; i < numberOfIncrements; i++) {
counter.increment();
}
assertEq(counter.number(), startingValue + numberOfIncrements);
}
// Fuzz test for combining setNumber and increment
function testFuzz_SetAndIncrement(uint256 x, uint8 incrementTimes) public {
counter.setNumber(x);
uint256 expectedValue = x;
for (uint i = 0; i < incrementTimes; i++) {
// Check for potential overflow
if (expectedValue < type(uint256).max) {
counter.increment();
expectedValue++;
} else {
// If we would overflow, don't increment anymore
break;
}
}
assertEq(counter.number(), expectedValue);
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
function setNumber(uint256 newNumber) public {
number = newNumber;
}
function increment() public {
number++;
}
}