Skip to content

Table Testing

Foundry v1.3.0 comes with support for table testing, which enables the definition of a dataset (the "table") and the execution of a test function for each entry in that dataset. This approach helps ensure that certain combinations of inputs and conditions are tested.

Test definition

In forge, table tests are functions named with table prefix that accepts datasets as one or multiple arguments:

function tableSumsTest(TestCase memory testCaseSum) public
function tableSumsTest(TestCase memory testCaseSum, bool enable) public

The datasets are defined as forge fixtures which can be:

  • storage arrays prefixed with fixture prefix and followed by dataset name
  • functions named with fixture prefix, followed by dataset name. Function should return an (fixed size or dynamic) array of values.

Examples

  • Single dataset. In following example, tableSumsTest test will be executed twice, with inputs from fixtureSums dataset: once with TestCase(1, 2, 3) and once with TestCase(4, 5, 9).
struct TestCase {
    uint256 a;
    uint256 b;
    uint256 expected;
}
    
function fixtureSums() public returns (TestCase[] memory) {
    TestCase[] memory entries = new TestCase[](2);
    entries[0] = TestCase(1, 2, 3);
    entries[1] = TestCase(4, 5, 9);
    return entries;
}
 
function tableSumsTest(TestCase memory sums) public pure {
    require(sums.a + sums.b == sums.expected, "wrong sum");
}
  • Multiple datasets. tableSwapTest test will be executed twice, by using values at the same position from fixtureWallet and fixtureSwap datasets.
struct Wallet {
    address owner;
    uint256 amount;
}
 
struct Swap {
    bool swap;
    uint256 amount;
}
    
Wallet[] public fixtureWallet;
Swap[] public fixtureSwap;
 
function setUp() public {
    // first table test input
    fixtureWallet.push(Wallet(address(11), 11));
    fixtureSwap.push(Swap(true, 11));
 
    // second table test input
    fixtureWallet.push(Wallet(address(12), 12));        
    fixtureSwap.push(Swap(false, 12));
}
 
function tableSwapTest(Wallet memory wallet, Swap memory swap) public pure {
    require(
        (wallet.owner == address(11) && swap.swap) || (wallet.owner == address(12) && !swap.swap), "not allowed"
    );
}