Version 3.0.0 - Now with TOML configuration, optional AI features, customizable mutation counts, and file filtering for large repositories!
A comprehensive mutation testing tool for Solidity smart contracts that helps identify weaknesses in your test suite. Uses Gambit for mutation generation and optionally leverages OpenAI for intelligent test generation.
Forge Mutation Tester uses Gambit to perform mutation testing on your Solidity contracts. It can optionally leverage OpenAI's GPT models to automatically generate tests that kill surviving mutants. All mutation results are stored for later analysis.
- 𧬠Mutation Testing: Automatically introduces small changes (mutations) to your code and checks if your tests catch them
- π€ AI-Powered Test Generation (Optional): Uses OpenAI to generate targeted tests for surviving mutations
- πΎ Persistent Results: Stores all mutation results in JSON format for later analysis
- π Iterative Testing: Re-run mutation testing after adding tests to track improvement
- π Local & Remote Repos: Works with both local projects and GitHub repositories
- π― Forge/Foundry Focused: Optimized specifically for Forge/Foundry projects
- π File Filtering: Target specific files or directories in large repositories using glob patterns
- Node.js >= 18.0.0
- Forge/Foundry installed
- Gambit mutation testing tool
- OpenAI API key (optional - only required for test generation)
# Install Rust if you haven't already
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install Gambit
cargo install --git https://github.com/Certora/gambit.gitnpm install -g forge-mutation-testerForge Mutation Tester uses a TOML configuration file. Create a mutation-config.toml file:
[repository]
# Option 1: Test a remote repository
# url = "https://github.com/owner/repo"
# branch = "main" # Optional
# token = "ghp_..." # Optional, for private repos
# Option 2: Test a local project
local_path = "./path/to/your/project"
[openai]
# api_key = "sk-..." # Optional - your OpenAI API key for test generation
# model = "gpt-4-turbo-preview" # Optional
[output]
directory = "mutation-results" # Optional
cleanup = true # Optional, only for remote repos
[testing]
# iterative = true # Optional, defaults to true
# num_mutants = 25 # Optional, defaults to 25
[files]
# Optional: Filter files for large repositories
# include = ["src/core/**/*.sol"] # Only test matching patterns
# exclude = ["**/*Test.sol"] # Skip these patterns
[solidity]
# Optional: Custom Solidity remappings
# remappings = ["@openzeppelin/=lib/openzeppelin/", "solmate/=lib/solmate/src/"]-
Generate an example configuration:
forge-mutation-tester init
-
Edit
mutation-config.tomlwith your settings -
Run mutation testing:
forge-mutation-tester mutation-config.toml
[repository]
local_path = "./my-defi-protocol"
[openai]
api_key = "sk-your-key-here"[repository]
url = "https://github.com/OpenZeppelin/openzeppelin-contracts"
branch = "master"
[openai]
api_key = "sk-your-key-here"For large repositories, you can focus mutation testing on specific files or directories:
[repository]
local_path = "./my-large-defi-protocol"
[files]
# Only test core contracts and governance
include = [
"contracts/core/**/*.sol",
"contracts/governance/**/*.sol",
"contracts/tokens/MainToken.sol"
]
# Skip test files, mocks, and deprecated code
exclude = [
"**/*Test.sol",
"**/test/**",
"**/mocks/**",
"contracts/deprecated/**",
"**/interfaces/**" # Interfaces have no implementation to mutate
]
[openai]
api_key = "sk-your-key-here"The file filtering uses glob patterns:
**- Matches any number of directories*- Matches any characters in a filename?- Matches a single character[abc]- Matches any character in the brackets{a,b}- Matches either pattern a or b
Common patterns:
src/**/*.sol- All Solidity files in src and subdirectoriescontracts/Token*.sol- All files starting with "Token" in contracts/**/*Test.sol- All test files in any directory**/interfaces/**- All files in any interfaces directory
If your project uses custom import paths that aren't automatically detected, you can specify them:
[solidity]
remappings = [
"@openzeppelin/=lib/openzeppelin-contracts/",
"@solmate-6.2.0/=dependencies/solmate-6.2.0/src/",
"solmate/=dependencies/solmate-6.2.0/src/",
"@myproject/=src/"
]This is particularly useful when:
- Auto-detection misses some dependencies
- You have non-standard dependency structures
- You're getting import resolution errors during mutation testing
- Your project uses versioned dependencies (e.g.,
@solmate-6.2.0/)
Iterative mode is enabled by default. To disable it and run only once:
[testing]
iterative = falseIn iterative mode:
- Run initial mutation testing
- Review and add generated tests to your project
- Tool prompts to continue
- Re-runs testing on previously survived mutations
- Shows improvement metrics
- Setup: Clones the repository (if remote) or uses your local project
- Mutation: Gambit generates mutants by making small changes to your Solidity code
- Testing: Runs your test suite against each mutant
- Analysis: Identifies mutations that survived (tests didn't catch the change)
- Generation: AI analyzes survived mutations and generates targeted tests
- Output: Saves generated tests and detailed reports
mutation-results/
βββ mutation-session.json # Complete session data with all iterations
βββ mutation-results.json # Latest mutation results
βββ mutation-results-iteration-N.json # Results for each iteration
βββ summary.json # Overall mutation testing results
βββ survived-mutations.json # Details of mutations that survived
βββ generated-tests/ # AI-generated test files (if API key provided)
β βββ Test_Contract1.t.sol
β βββ Test_Contract2.t.sol
βββ analysis-report.md # Human-readable analysis
The tool works perfectly fine without an OpenAI API key. You can:
- Run mutation testing to identify weaknesses in your test suite
- View detailed reports of which mutations survived
- Manually write tests to kill the surviving mutations
- Re-run to see your progress
To use without AI:
[repository]
local_path = "./my-project"
# [openai] section can be omitted entirely- Start with a working test suite: Ensure
forge testpasses before running mutation testing - Review generated tests: AI-generated tests should be reviewed before adding to your suite
- Use iterative mode: Progressively improve test quality by adding tests and re-running
- Focus on critical contracts: Test your most important contracts first
- Adjust gas limits: Some mutations might cause infinite loops; tests with appropriate gas limits help detect these
- Ensure your project compiles:
forge build - Check that source files are in standard locations (
src/,contracts/) - Verify Gambit is installed:
gambit --version
- Install Foundry: https://book.getfoundry.sh/getting-started/installation
- Ensure forge is in your PATH
- Some mutations create invalid code (expected behavior)
- Focus on mutations that compile but aren't caught by tests
Contributions are welcome! Please feel free to submit issues and pull requests.
MIT