Roadmap › Solidity & Smart Contract Development › Module: Advanced Topics
Lessons in this course (11)
11. Testing with Foundry and Hardhat, deployment
Intermediate★ Must knowLesson 11 of 11
solidity
// test/SimpleBank.t.sol (Foundry)
import {Test} from "forge-std/Test.sol";
import {SimpleBank} from "../src/SimpleBank.sol";
contract SimpleBankTest is Test {
SimpleBank bank;
address alice = makeAddr("alice");
function setUp() public { bank = new SimpleBank(); vm.deal(alice, 10 ether); }
function test_DepositAndWithdraw() public {
vm.startPrank(alice);
bank.deposit{value: 1 ether}();
bank.withdraw(0.4 ether);
vm.stopPrank();
assertEq(bank.balances(alice), 0.6 ether);
}
function test_RevertWhen_WithdrawTooMuch() public {
vm.prank(alice);
vm.expectRevert(abi.encodeWithSelector(SimpleBank.InsufficientBalance.selector, 1 ether, 0));
bank.withdraw(1 ether);
}
function testFuzz_Deposit(uint96 amount) public { // fuzzing: random inputs
vm.assume(amount >= 0.01 ether && amount <= 10 ether);
vm.prank(alice);
bank.deposit{value: amount}();
assertEq(bank.totalDeposits(), amount);
}
}bash
forge init bank && forge build && forge test -vvv
forge test --gas-report && forge coverage
anvil # local node
forge script script/Deploy.s.sol --rpc-url $SEPOLIA_RPC --account deployer --broadcast --verify
cast call <address> "balances(address)(uint256)" <alice> --rpc-url $SEPOLIA_RPC
# Hardhat alternative
npx hardhat test
npx hardhat ignition deploy ./ignition/modules/Bank.ts --network sepolia --verifyTest types: unit, fuzz, invariant (properties that must always hold across random call sequences), fork tests (against real mainnet state), integration with frontends. Keep deployer keys in an encrypted keystore or hardware wallet — never in .env committed to Git.