Introduction
This page covers advanced testing techniques for assertions. All testing tools available in Forge are also available in Credible Layer testing, making it powerful and easy to write comprehensive tests for assertions.Fuzz Testing
Fuzz testing is a technique for testing general robustness of code by running many tests with random inputs. This is useful for assertions as it helps identify edge cases and unexpected behavior. You can use Forge’s built-in fuzz testing capabilities to test your assertions with random inputs.withdrawalAmount
that adhere to the bounds set by the vm.assume()
constraints.
Use
vm.assume()
to filter out invalid inputs that would cause the test to fail for reasons unrelated to your assertion logic.CI/CD Integration
You can set up CI/CD workflows to ensure all assertion tests pass before merging code. The setup is very similar to standard Foundry/Forge workflows, with the addition of installingpcl
and running pcl test
for testing.
- Triggers on pull requests to main/develop branches when assertion or source files change
- Supports manual runs with
workflow_dispatch
- Uses the assertions profile via
FOUNDRY_PROFILE: assertions
- Installs the latest PCL CLI from GitHub releases
- Runs all assertion tests with
pcl test
Use the
FOUNDRY_PROFILE: assertions
environment variable to ensure the correct Foundry profile is used for testing assertions.Foundry Profile Configuration
Foundry profiles allow you to configure different compilation and testing settings for different parts of your project. For assertions, you typically want a separate profile that focuses on the assertion-specific source code. This configuration goes in your project’sfoundry.toml
file, which you should be familiar with if you have used Foundry before.
assertions
profile:
- Separate source directory (
assertions/src
) - Keeps assertion code isolated - Separate output directory (
assertions/out
) - Prevents conflicts with main project artifacts - Same compiler settings - Ensures consistency with main project
pcl test
or setting FOUNDRY_PROFILE=assertions
, Foundry uses this profile configuration instead of the default one.
You can set the FOUNDRY_PROFILE
environment variable to assertions
in your CI/CD workflow. Or you can specify the profile to use when running tests like this:
Backtesting
Backtesting runs your assertions against actual historical transactions from a specified block range. This helps ensure your assertions work correctly with real transaction patterns and don’t trigger false positives on legitimate protocol operations.RPC Call Requirements
Backtesting makes RPC calls in two phases:- Transaction Fetching: 1 RPC call per block using
eth_getBlockByNumber
- Transaction Validation: 1 RPC call per transaction that triggers the assertion (via
vm.createSelectFork
)
- If 100 blocks contain 50 transactions that trigger your assertion:
- Fetching phase: 100 RPC calls
- Validation phase: 50 RPC calls
- Total: 150 RPC calls
For larger block ranges (>1,000 blocks), consider using paid RPC providers to avoid rate limiting issues.
Example
CredibleTest
, so you need to inherit from CredibleTestWithBacktesting
instead of CredibleTest
. From here it’s straightforward to write tests that run against historical transactions. The executeBacktest
function returns a BacktestingTypes.BacktestingResults
struct that contains the results of the backtest.
Consider excluding the backtesting from your CI/CD pipeline as it can take a long time to run. Backtesting should be run manually on demand to increase confidence in your assertions before a deployment.
Running Backtesting Tests
You can specify the RPC URL either as an environment variable or as a parameter:Backtesting requires the
--ffi
flag to enable foreign function interface for RPC calls. It can take quite some time to fetch old transactions and run the tests, so start out with small block ranges until you are confident everything is set up properly and then expand to larger ranges.API Reference
BacktestingResults
TheBacktestingResults
struct contains the results of the backtest:
Start with a small block range to test your assertion logic, then expand to larger ranges once you’re confident in the results.