Paul Berg
Solidity Summit: Nov 16, 2023
function test_Foo() external {
uint256 x = 42;
assertEq(contract.foo(x), x, "value mismatch");
}
function test_Foo_1() external {
// --- snip ---
}
function test_Foo_2() external {
// --- snip ---
}
function test_Foo_3(uint256 arg0) external {
// --- snip ---
}
function test_Foo_4(uint256 arg0, uint256 arg1) external {
// --- snip ---
}
Technique | Barrier to entry | Effectiveness |
---|---|---|
Braching Tree Technique | Entry-level | Moderately effective |
Cucumber Gherkin | Medium-level | Moderately effective |
Certora, K Framework, TLA+ | Senior-level | Highly effective |
when.tree
WhenTest
├── when x is false
│ └── it should revert
└── when x is true
└── it should return x
when.t.sol
contract WhenTest {
function test_RevertWhen_XIsFalse() external {
// it should revert
}
function test_WhenXIsTrue() external {
// it should return x
}
}
when.t.sol
contract WhenTest {
function test_RevertWhen_XIsFalse() external {
vm.expectRevert("x must not be false");
foo.simpleWhen({ x: false });
}
function test_WhenXIsTrue() external {
bool result = foo.simpleWhen({ x: true });
assertTrue(result);
}
}
givenWhen.tree
GivenWhenTest
├── given value is less than 100
│ └── it should revert
└── given value is not less than 100
├── when x is false
│ └── it should revert
└── when x is true
└── it should return x
givenWhen.t.sol
contract GivenWhenTest is BaseTest {
function test_RevertGiven_ValueIsLessThan100()
external
{
// it should revert
}
modifier givenValueIsNotLessThan100() {
foo.setValue({ newValue: 1337 });
_;
}
function test_RevertWhen_XIsFalse()
external
givenValueIsNotLessThan100
{
// it should revert
}
function test_WhenXIsTrue()
external
givenValueIsNotLessThan100
{
// it should return x
}
}
Scenario | Answer |
---|---|
Is it a contract state that is prepared in advance? | Given |
Is it a mode of execution, e.g. call vs delegatecall? | When |
Is it a function parameter that the user is in control when calling the function? | When |