foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.25k stars 1.73k forks source link

feat(forge): new cheatcode for running simple tests with multiple `msg.sender` values #4839

Open PaulRBerg opened 1 year ago

PaulRBerg commented 1 year ago

Component

Forge

Describe the feature you would like

Scenario: a contract function allows the caller to be one of two special accounts:

function foo() external onlyAliceOrBob {
    // <--- snip --- >
}

Testing this sort of function is annoying because I have to duplicate logic in my tests, e.g.

function testFoo_Alice() external {
    assertEq(A, B);
    assertEq(C, D);
    assertEq(E, F);
}

function testFoo_Bob() external {
    assertEq(A, B);
    assertEq(C, D);
    assertEq(E, F);
}

Now, I know I could de-dup the assertions in a subroutine, like this:

function testFoo_Common() internal {
    // <--- snip --->
}

But I wouldn't say I like this approach because it (i) hurts the readability of the tests and (ii) doesn't scale super well (e.g. in realistic scenarios, Bob has specific permissions that Alice doesn't have, which requires branching, which in turn complicates the subroutine).

It would be helpful if Forge lent a hand for this use case. I imagine that a new cheatcode could be implemented, e.g. vm.consider, which would be similar to vm.assume and would work something like this:

With this hypothetical vm.consider, I could write my test like this:

function testFoo() external {
    vm.consider(users.alice, users.bob); // succinct and declarative
    assertEq(A, B);
    assertEq(C, D);
    assertEq(E, F);
}

Side notes:

mds1 commented 1 year ago

Is this a duplicate of https://github.com/foundry-rs/foundry/issues/858? It sounds like a more narrow version that issue

PaulRBerg commented 1 year ago

This is not quite the same as #858 (table tests).

A table test is an explicit set of input(s) + output(s).

Whereas in this issue, I suggested implementing a new mode of unit testing, a mode specifically meant for unit testing a range of callers. There's no notion of outputs in my proposal.