How to Write and Run Unit Tests with `forc test` in Sway
The forc test command compiles and executes all functions annotated with #[test] in a Sway package, running them on the Fuel VM and reporting pass/fail status, gas usage, and optional logs.
The forc test command is the official test harness for the Sway language, maintained in the FuelLabs/sway repository. It provides a zero-configuration workflow for unit testing smart contracts and scripts by compiling each #[test] function as an independent entry point and executing it within the Fuel VM environment.
Writing Tests for forc test
Basic Unit Tests
Mark any function with the #[test] attribute to register it as a test entry point. The function must take no arguments and return unit ().
#[test]
fn test_meaning_of_life() {
assert(6 * 7 == 42);
}
Testing Revert Conditions
Use #[test(should_revert)] when you expect a test to fail by reverting. The test passes only if execution triggers a rvrt instruction.
#[test(should_revert)]
fn test_fails_on_wrong_result() {
// This will revert because the assertion is false.
assert_eq(6 * 6, 42);
}
To assert a specific revert code, provide the 64-bit decimal value as a string:
#[test(should_revert = "18446744073709486084")]
fn test_specific_revert() {
assert_eq(6 * 6, 42);
}
Testing Contract Calls
When testing contract logic, forc test automatically builds the contract without tests first to compute CONTRACT_ID, then rebuilds with tests and injects that identifier into the test namespace.
contract;
abi MyContract {
fn greet() -> bool;
}
impl MyContract for Contract {
fn greet() -> bool {
true
}
}
#[test]
fn test_contract_call() {
let caller = abi(MyContract, CONTRACT_ID);
let result = caller.greet {}();
assert(result == true);
}
Logging Inside Tests
Use the log() function to emit values during test execution. Logs are captured as Log or LogData receipts on the Fuel VM.
script;
fn main() {}
#[test]
fn test_with_logs() {
let a = 10;
log(a);
let b = 30;
log(b);
assert_eq(a, 10);
assert_eq(b, 30);
}
Running Tests with forc test
Basic Invocation
Execute all tests in the current package:
forc test
This compiles the package with the is_test flag set in sway-core/src/build_config.rs and runs each test binary on the Fuel VM.
Filtering Tests
Run only tests whose names contain a specific substring:
forc test mean
Run a single test by exact name match:
forc test --filter-exact test_meaning_of_life
The filtering logic is implemented via TestFilter in forc/src/cli/commands/test.rs.
Controlling Parallelism
By default, forc test uses as many threads as available CPU cores. Force single-threaded execution for deterministic log ordering:
forc test --test-threads 1
This maps to TestRunnerCount in the forc_test crate.
Output and Debugging Options
Control the verbosity and format of test results:
-l/--logs— Decode and printLog/LogDatareceipts (seeprint_test_outputinforc/src/cli/commands/test.rs).--raw-logs— Display raw log receipts as JSON.--pretty— Pretty-print raw JSON logs.--reverts— Show revert codes and error messages for failing orshould_reverttests.--dbgs— Print debug output fromdbg!captures.--silent— Suppress the summary output (useful in CI pipelines).
Example combining multiple flags:
forc test --logs --raw-logs --pretty --reverts
Gas Usage Reporting
forc test reports gas consumed for each test (e.g., (..., 512 gas)). Override the default gas cost table with:
forc test --gas-costs testnet
Valid options include built-in, mainnet, testnet, or a path to a custom JSON file.
How forc test Works Internally
The test harness follows a multi-stage pipeline defined in the forc-test crate and orchestrated from forc/src/cli/commands/test.rs:
- CLI Parsing — The
Commandstruct intest.rsdefines all flags (filtering, threading, output options) and theexecentry point. - Build Step —
forc_test::build(opts)compiles each#[test]function as an independent entry point. Theis_testflag insway-core/src/build_config.rsenables test-specific compilation paths. - Execution —
built_tests.run(...)spawns the Fuel VM for each compiled artifact, respectingTestRunnerCountfor parallelism. - Result Processing —
print_tested_pkgiterates overTestResultstructs, formatting pass/fail markers, gas usage, and delegating toprint_test_outputfor logs. - Exit Code — If any test fails,
execreturns exit code 101; otherwise 0 (lines 57–65 oftest.rs).
Quick Reference Cheat Sheet
# Run all tests
forc test
# Run tests matching a substring
forc test math
# Run exact test name
forc test --filter-exact test_math_addition
# Single-threaded execution
forc test --test-threads 1
# Show logs and revert details
forc test --logs --reverts
# Pretty-print raw logs
forc test --raw-logs --pretty
# Custom gas costs
forc test --gas-costs testnet
# Silent mode for CI
forc test --silent
Summary
- Annotate test functions with
#[test]or#[test(should_revert)]to mark them as entry points forforc test. - The command compiles each test as an independent binary, executes it on the Fuel VM, and reports gas usage alongside pass/fail status.
- Use
--filter-exactto run single tests and--test-threadsto control parallelism. - Access logs with
--logsor--raw-logs, and inspect revert codes with--reverts. - The implementation resides in
forc/src/cli/commands/test.rsand theforc-testcrate, using theis_testflag insway-core/src/build_config.rsto enable test-specific compilation.
Frequently Asked Questions
How do I run a single specific test with forc test?
Use the --filter-exact flag followed by the full function name. For example, forc test --filter-exact test_meaning_of_life runs only that function. Without this flag, providing a positional argument acts as a substring filter, running all tests whose names contain the provided text.
Can I view logs from tests that pass?
By default, logs are suppressed for passing tests. To view them, add the -l or --logs flag to decode and display Log and LogData receipts. For raw VM receipt data, use --raw-logs, and combine with --pretty for formatted JSON output.
What exit code does forc test return on failure?
The command exits with status 101 if any test fails, and 0 on complete success. This behavior is defined in the exec function within forc/src/cli/commands/test.rs (lines 57–65) and follows Rust’s testing convention, making it suitable for CI pipelines that check exit status.
How do I test that a function reverts with a specific error code?
Annotate the test with #[test(should_revert = "18446744073709486084")], providing the 64-bit decimal representation of the expected revert code. The test harness compares the actual revert code from the VM against this value, and the test passes only if they match.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →