|
| 1 | +# Fork Testing Pragma |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The `#test_fork` pragma is the **recommended way** to configure fork tests in Cadence. It configures tests to run against a snapshot of a live Flow network (mainnet or testnet), allowing you to test against real deployed contracts and production data without deploying anything to the live network. |
| 6 | + |
| 7 | +**Why use the pragma?** |
| 8 | + |
| 9 | +- ✅ **No CLI flags required** - Test configuration lives in your test file |
| 10 | +- ✅ **Works with `flow test`** - No special commands needed |
| 11 | +- ✅ **Self-documenting** - Other developers can see the test is forked just by reading the file |
| 12 | +- ✅ **Mix test types freely** - Run local tests and fork tests with a single `flow test` command |
| 13 | +- ✅ **No flow.json changes** - Test configuration stays with the test code |
| 14 | + |
| 15 | +## Syntax |
| 16 | + |
| 17 | +```cadence |
| 18 | +#test_fork(network: "mainnet", height: nil) |
| 19 | +``` |
| 20 | + |
| 21 | +Place the pragma at the top of your test file, before any imports. |
| 22 | + |
| 23 | +## Parameters |
| 24 | + |
| 25 | +### `network` (required) |
| 26 | + |
| 27 | +The Flow network to fork from. |
| 28 | + |
| 29 | +**Valid values:** |
| 30 | + |
| 31 | +- `"mainnet"` - Fork from Flow mainnet |
| 32 | +- `"testnet"` - Fork from Flow testnet |
| 33 | +- Any network name defined in your `flow.json` networks configuration |
| 34 | + |
| 35 | +### `height` (optional) |
| 36 | + |
| 37 | +The block height to fork from. |
| 38 | + |
| 39 | +**Valid values:** |
| 40 | + |
| 41 | +- `nil` - Use the latest sealed block (recommended for most cases) |
| 42 | +- `UInt64` - Fork from a specific historical block height (e.g., `height: 85229104`) |
| 43 | + |
| 44 | +## Purpose |
| 45 | + |
| 46 | +Fork testing enables: |
| 47 | + |
| 48 | +1. **Integration testing** - Test interactions with real deployed contracts without deploying your own |
| 49 | +2. **Account impersonation** - Execute transactions as any mainnet account without private keys |
| 50 | +3. **Production state validation** - Verify behavior against actual on-chain data |
| 51 | +4. **Historical debugging** - Test against blockchain state at a specific block height |
| 52 | + |
| 53 | +## Examples |
| 54 | + |
| 55 | +### Basic Fork Test (Latest Block) |
| 56 | + |
| 57 | +```cadence |
| 58 | +#test_fork(network: "mainnet", height: nil) |
| 59 | +
|
| 60 | +import Test |
| 61 | +import "SomeMainnetContract" |
| 62 | +
|
| 63 | +access(all) fun testAgainstMainnet() { |
| 64 | + // Test code runs against mainnet state |
| 65 | + let account = Test.getAccount(0x1234567890abcdef) |
| 66 | + // All changes happen locally in test environment |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +### Fork Test at Specific Height |
| 71 | + |
| 72 | +```cadence |
| 73 | +#test_fork(network: "mainnet", height: 85229104) |
| 74 | +
|
| 75 | +import Test |
| 76 | +
|
| 77 | +access(all) fun testHistoricalState() { |
| 78 | + // Test against blockchain state at block 85229104 |
| 79 | + // Useful for reproducing historical bugs or validating fixes |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +### Using Custom Network from flow.json |
| 84 | + |
| 85 | +```cadence |
| 86 | +#test_fork(network: "previewnet", height: nil) |
| 87 | +
|
| 88 | +import Test |
| 89 | +
|
| 90 | +access(all) fun testOnPreviewnet() { |
| 91 | + // Forks from custom network defined in your flow.json |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +## Running Fork Tests |
| 96 | + |
| 97 | +The beauty of the `#test_fork` pragma is that you don't need any special flags: |
| 98 | + |
| 99 | +```bash |
| 100 | +# Run all tests - local AND fork tests work together! |
| 101 | +flow test |
| 102 | + |
| 103 | +# Run a specific fork test |
| 104 | +flow test path/to/fork_test.cdc |
| 105 | + |
| 106 | +# Run only local tests (exclude fork tests) |
| 107 | +flow test --skip-fork |
| 108 | +``` |
| 109 | + |
| 110 | +**No need for:** |
| 111 | + |
| 112 | +- ❌ `flow test --fork mainnet` flags |
| 113 | +- ❌ `flow test --fork-host` configuration |
| 114 | +- ❌ Different commands for different test types |
| 115 | + |
| 116 | +Just use `flow test` and the pragma handles everything! |
| 117 | + |
| 118 | +## Best Practices |
| 119 | + |
| 120 | +### Use the Pragma (Not CLI Flags) |
| 121 | + |
| 122 | +**Recommended:** |
| 123 | + |
| 124 | +```cadence |
| 125 | +#test_fork(network: "mainnet", height: nil) |
| 126 | +import Test |
| 127 | +// Test code... |
| 128 | +``` |
| 129 | + |
| 130 | +**Not Recommended:** |
| 131 | + |
| 132 | +```bash |
| 133 | +flow test --fork mainnet path/to/test.cdc # Requires flags every time |
| 134 | +``` |
| 135 | + |
| 136 | +The pragma keeps fork configuration with your test code where it belongs. |
| 137 | + |
| 138 | +### Organize Your Tests |
| 139 | + |
| 140 | +``` |
| 141 | +tests/ |
| 142 | + ├── unit_tests/ # Local tests |
| 143 | + │ └── contract_test.cdc |
| 144 | + └── integration_tests/ # Fork tests |
| 145 | + └── mainnet_integration_test.cdc |
| 146 | +``` |
| 147 | + |
| 148 | +Run everything with: `flow test` |
| 149 | + |
| 150 | +## Notes |
| 151 | + |
| 152 | +- Fork tests require network connectivity to access the forked network |
| 153 | +- All mutations occur only in your local test environment |
| 154 | +- Fork tests are slightly slower than local tests due to network state fetching |
| 155 | +- The pragma makes it easy to mix fork tests and regular tests in the same test suite |
| 156 | +- CI/CD friendly - no special configuration needed, just `flow test` |
0 commit comments