diff --git a/src/SUMMARY.md b/src/SUMMARY.md index e67f33757..c47898c0e 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -5,29 +5,32 @@ # Getting Started - [Installation](./getting-started/installation.md) -- [First Steps with Foundry](./getting-started/first-steps.md) - -# Projects - + - [Creating a New Project](./projects/creating-a-new-project.md) - [Working on an Existing Project](./projects/working-on-an-existing-project.md) - [Dependencies](./projects/dependencies.md) - [Project Layout](./projects/project-layout.md) +# Testing + +- [Basics of Testing With Foundry](./testing/tests.md) + - [Writing Tests](./testing/writing-tests.md) + - [Cheatcodes](./testing/cheatcodes.md) + - [Forge Standard Library Overview](./testing/forge-std.md) + - [Understanding Traces](./testing/traces.md) + - [Fork Testing](./testing/fork-testing.md) +- [Advanced Testing](./testing/advanced-testing.md) + - [Fuzz Testing](./testing/fuzz-testing.md) + - [Invariant Testing](./testing/invariant-testing.md) + - [Differential Testing](./testing/differential-ffi-testing.md) + + + # Forge Overview - [Overview of Forge](forge/README.md) -- [Tests](./forge/tests.md) - - [Writing Tests](./forge/writing-tests.md) - - [Cheatcodes](./forge/cheatcodes.md) - - [Forge Standard Library Overview](./forge/forge-std.md) - - [Understanding Traces](./forge/traces.md) - - [Fork Testing](./forge/fork-testing.md) + - [Testing Overview](forge/testing.md) ! -- [Advanced Testing](./forge/advanced-testing.md) - - [Fuzz Testing](./forge/fuzz-testing.md) - - [Invariant Testing](./forge/invariant-testing.md) - - [Differential Testing](./forge/differential-ffi-testing.md) @@ -51,31 +54,9 @@ - [Overview of Chisel](./chisel/README.md) -# Configuration - -- [Configuring with `foundry.toml`](./config/README.md) -- [Continuous Integration](./config/continous-integration.md) -- [Integrating with VSCode](./config/vscode.md) -- [Shell Autocompletion](./config/shell-autocompletion.md) -- [Static Analyzers](./config/static-analyzers.md) -- [Integrating with Hardhat](./config/hardhat.md) - -# Tutorials - -- [Best Practices](./tutorials/best-practices.md) -- [Creating an NFT with Solmate](./tutorials/solmate-nft.md) -- [Docker and Foundry](./tutorials/foundry-docker.md) -- [Testing EIP-712 Signatures](./tutorials/testing-eip712.md) -- [Solidity Scripting](./tutorials/solidity-scripting.md) -- [Forking Mainnet with Cast and Anvil](./tutorials/forking-mainnet-with-cast-anvil.md) -- [Learning Foundry Videos](./tutorials/learn-foundry.md) - - -# Appendix +# References -- [FAQ](./faq.md) -- [Help us improve Foundry](./contributing.md) -- [References](./reference/README.md) +- [References by tool](./reference/README.md) - [`forge` Commands](./reference/forge/README.md) - [General Commands](./reference/forge/general-commands.md) - [forge](./reference/forge/forge.md) @@ -346,6 +327,32 @@ - [`deriveRememberKey`](./reference/forge-std/derive-remember-key.md) - [Console Logging](./reference/forge-std/console-log.md) - [DSTest Reference](./reference/ds-test.md) + +# Tutorials + +- [Best Practices](./tutorials/best-practices.md) +- [Creating an NFT with Solmate](./tutorials/solmate-nft.md) +- [Docker and Foundry](./tutorials/foundry-docker.md) +- [Testing EIP-712 Signatures](./tutorials/testing-eip712.md) +- [Solidity Scripting](./tutorials/solidity-scripting.md) +- [Forking Mainnet with Cast and Anvil](./tutorials/forking-mainnet-with-cast-anvil.md) +- [Invariant Testing a Bonding Curve](./tutorials/invariant-testing-bonding-curve.md) +- [Learning Foundry Videos](./tutorials/learn-foundry.md) + + +# Configuration + +- [Configuring with `foundry.toml`](./config/README.md) +- [Continuous Integration](./config/continous-integration.md) +- [Integrating with VSCode](./config/vscode.md) +- [Shell Autocompletion](./config/shell-autocompletion.md) +- [Static Analyzers](./config/static-analyzers.md) +- [Integrating with Hardhat](./config/hardhat.md) + +# Appendix + +- [FAQ](./faq.md) +- [Help us improve Foundry](./contributing.md) - [Miscellaneous](./misc/README.md) - [Struct encoding](./misc/struct-encoding.md) - [Precompile Registry](./misc/precompile-registry.md) diff --git a/src/cheatcodes/expect-call.md b/src/cheatcodes/expect-call.md index 71ff38aa9..7941000e1 100644 --- a/src/cheatcodes/expect-call.md +++ b/src/cheatcodes/expect-call.md @@ -27,7 +27,7 @@ function expectCall( ### Description -Expects that a call to a specified address `where`, where the call data either strictly or loosely matches `data`. The cheatcode can be called in two ways: +Expects that a call to a specified address `where`, where the call data either strictly or loosely matches `data`, in the next call's subcalls. The cheatcode can be called in two ways: - If no `count` parameter is specified, the call will be expected to be made at least the amount of times the cheatcode was called. For the same calldata, you cannot call the cheatcode with no `count` and then pass in a `count` parameter. - If `count` is specified, the call will be expected to be made strictly `count` times. For the same calldata, the `count` value cannot be overwritten with another cheatcode call, nor it can be increment by calling the cheatcode without a `count` parameter. diff --git a/src/cheatcodes/expect-revert.md b/src/cheatcodes/expect-revert.md index 20223038b..5e2584596 100644 --- a/src/cheatcodes/expect-revert.md +++ b/src/cheatcodes/expect-revert.md @@ -18,9 +18,9 @@ function expectRevert(bytes calldata message) external; If the **next call** does not revert with the expected data `message`, then `expectRevert` will. -After calling `expectRevert`, calls to other cheatcodes before the reverting call are ignored. +After calling `expectRevert`, calls to other cheatcodes before the reverting call are ignored. However, using other `expect` cheatcodes with `expectRevert` is forbidden and will cause the test to fail. -This means, for example, we can call [`prank`](./prank.md) immediately before the reverting call. +This means, for example, we can call [`prank`](./prank.md) immediately before the reverting call, but we cannot call [`expectEmit`](./expect-emit.md) immediately before the reverting call. There are 3 signatures: diff --git a/src/forge/testing.md b/src/forge/testing.md new file mode 100644 index 000000000..641c8b158 --- /dev/null +++ b/src/forge/testing.md @@ -0,0 +1,58 @@ +## Testing + +Forge's flagship feature is testing. Tests are performed using Solidity, and it's blazing fast. + +## Unit tests + +Unit tests make up the most basic form of testing supported by Forge. + +```sh +{{#include ../output/hello_foundry/forge-test:all}} +``` + +For more information on unit tests, go [to the Testing section](../testing/tests.md). + +## Property Based Tests + +Property based tests are also supported in forge. They're really effective for testing general behavior and uncovering edge cases. + +Writing a fuzz tests is as easy as creating a normal test function with parameters. + +```solidity +pragma solidity 0.8.10; + +import "forge-std/Test.sol"; + +contract ContractBTest is Test { + uint256 testNumber; + + function setUp() public { + testNumber = 42; + } + + function add(uint256 a, uint256 b) external returns (uint256) { + return a + b; + } + + function test_fuzzAdd(uint256 x, uint256 y) public { + // We can limit the range of our inputs using bound. + x = bound(x, 0, 100); + y = bound(y, 0, 100); + uint256 result = add(x, y); + assertEq(x + y, result); + } +} +``` + +For more information on property based tests, go [to the fuzz testing page on the Testing section](../testing/fuzz-testing.md). + +## Stateful Fuzz Tests + +Stateful fuzz tests (also commonly called Invariant Tests in the community) are a really useful form of advanced testing available on Foundry. They allow for a set of invariant expressions to be tested against randomized sequences of pre-defined function calls from pre-defined contracts. After each function call is performed, all defined invariants are asserted. + +For more information on stateful fuzz tests, go [to the stateful fuzz testing page on the Testing section](../testing/invariant-testing.md). + +## Cheatcodes + +Forge has a powerful feature to help you write comprehensive tests for your smart contract suite called cheatcodes. They help you manipulate the state of the local blockchain and EVM, which means you can easily replicate extreme conditions on your tests or mainnet conditions outright. They're easily accessible through the `vm` instance available in Forge Standard Library's `Test` contract. + diff --git a/src/output/invariant_tut/directories b/src/output/invariant_tut/directories new file mode 100644 index 000000000..4b25f64fd --- /dev/null +++ b/src/output/invariant_tut/directories @@ -0,0 +1,14 @@ +// ANCHOR: all +// ANCHOR: command +$ tree . -d -L 1 +// ANCHOR_END: command +// ANCHOR: output +. +├── Makefile +├── foundry.toml +├── test +└──── invariant + +4 directories +// ANCHOR_END: output +// ANCHOR_END: all diff --git a/src/forge/advanced-testing.md b/src/testing/advanced-testing.md similarity index 100% rename from src/forge/advanced-testing.md rename to src/testing/advanced-testing.md diff --git a/src/forge/cheatcodes.md b/src/testing/cheatcodes.md similarity index 100% rename from src/forge/cheatcodes.md rename to src/testing/cheatcodes.md diff --git a/src/forge/differential-ffi-testing.md b/src/testing/differential-ffi-testing.md similarity index 100% rename from src/forge/differential-ffi-testing.md rename to src/testing/differential-ffi-testing.md diff --git a/src/forge/forge-std.md b/src/testing/forge-std.md similarity index 100% rename from src/forge/forge-std.md rename to src/testing/forge-std.md diff --git a/src/forge/fork-testing.md b/src/testing/fork-testing.md similarity index 100% rename from src/forge/fork-testing.md rename to src/testing/fork-testing.md diff --git a/src/forge/fuzz-testing.md b/src/testing/fuzz-testing.md similarity index 100% rename from src/forge/fuzz-testing.md rename to src/testing/fuzz-testing.md diff --git a/src/forge/invariant-testing.md b/src/testing/invariant-testing.md similarity index 100% rename from src/forge/invariant-testing.md rename to src/testing/invariant-testing.md diff --git a/src/forge/tests.md b/src/testing/tests.md similarity index 92% rename from src/forge/tests.md rename to src/testing/tests.md index d90aa9725..1cb043bc5 100644 --- a/src/forge/tests.md +++ b/src/testing/tests.md @@ -1,5 +1,7 @@ ## Tests +Testing on Foundry is done using `forge`. Here we'll learn how to perform basic and more advanced testing and to leverage unique functionality such as cheatcodes. + Forge can run your tests with the [`forge test`](../reference/forge/forge-test.md) command. All tests are written in Solidity. Forge will look for the tests anywhere in your source directory. Any contract with a function that starts with `test` is considered to be a test. Usually, tests will be placed in `test/` by convention and end with `.t.sol`. diff --git a/src/forge/traces.md b/src/testing/traces.md similarity index 100% rename from src/forge/traces.md rename to src/testing/traces.md diff --git a/src/forge/writing-tests.md b/src/testing/writing-tests.md similarity index 100% rename from src/forge/writing-tests.md rename to src/testing/writing-tests.md diff --git a/src/tutorials/invariant-testing-bonding-curve.md b/src/tutorials/invariant-testing-bonding-curve.md index 3107d160b..414dc6928 100644 --- a/src/tutorials/invariant-testing-bonding-curve.md +++ b/src/tutorials/invariant-testing-bonding-curve.md @@ -3,11 +3,11 @@ ### Introduction -This tutorial will cover invariant testing, using **Bonding Curve Implementation** as a target example. All invariant tests are written in Solidity using the `Foundry Invaraint Testing` feature. +This tutorial will cover invariant testing, using **Bonding Curve Implementation** as a target example. All invariant tests are written in Solidity using the `Foundry Invariant Testing` feature. However, this guide is for educational purposes only. The code is not audited. Please do not use it in production. -> 💡 Note: A full implementation of the bonding curve can be found [here](https://github.com/Ratimon/bonding-curves), and for further reading about invariant testing, we can check out the `Invariant Testing` [reference](../reference/forge/invariant-testing.md). +> 💡 Note: A full implementation of the bonding curve can be found [here](https://github.com/Ratimon/bonding-curves), and for further reading about invariant testing, we can check out the `Invariant Testing` [reference](../forge/invariant-testing.md). ### Quick Start @@ -27,17 +27,7 @@ The key consderation is to define these: 2. **Actions** (a set of things that can happen during each run) -To get started, we are going to focus on the following directories in this [repository](https://github.com/Ratimon/bonding-curves): - -``` -. -├── Makefile -├── foundry.toml -└── test - ├── invariant -``` - -In this guide, we can run the fuzzing campagin by running the following command: +To get started, make sure to clone the repository. All commands will be available in the `Makefile`. We can run the fuzzing campagin by running the following command: ```sh make invariant-LinearBondingCurve