From c19a268fecac1b12f9c66c36990751e7e7e7ea79 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 7 Oct 2025 18:22:18 -0700 Subject: [PATCH 01/23] Update Flow Emulator Reference Doc --- docs/build/tools/emulator/index.md | 90 ++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 6 deletions(-) diff --git a/docs/build/tools/emulator/index.md b/docs/build/tools/emulator/index.md index 451e772a64..ff248a2aa1 100644 --- a/docs/build/tools/emulator/index.md +++ b/docs/build/tools/emulator/index.md @@ -29,20 +29,98 @@ This starts a local Flow network with: - REST API on `http://localhost:8888` - Admin API on port `8080` -## Common Options +## Available Commands + +- `snapshot`: Create/Load/List emulator snapshots. See: [Create Emulator Snapshot](../flow-cli/deployment/emulator-snapshot.md) + +## Key Flags + +- **Networking** + - `--host `: Host to listen on for gRPC/REST/Admin (default: all interfaces) + - `--port, -p `: gRPC port (default `3569`) + - `--rest-port `: REST API port (default `8888`) + - `--admin-port `: Admin API port (default `8080`) + - `--debugger-port `: Debug Adapter Protocol port (default `2345`) + - `--grpc-debug`: Enable gRPC server reflection + - `--rest-debug`: Enable REST API debug output + +- **State & Persistence** + - `--persist`: Enable persistent storage (default disabled) + - `--dbpath `: Directory for on-disk state (default `./flowdb`) + - `--sqlite-url `: Use SQLite storage backend + - `--redis-url `: Use Redis storage backend + - `--checkpoint-dir `: Load state from checkpoint directory + - `--state-hash `: Load state from checkpoint state hash + +- **Forking** + - `--rpc-host `: Access node to query when forking Mainnet/Testnet + - `--start-block-height `: Starting block height when forking + +- **Cadence & VM** + - `--block-time, -b `: Time between sealed blocks (e.g. `1s`, `300ms`) + - `--coverage-reporting`: Enable code coverage reporting + - `--computation-reporting`: Enable computation reporting + - `--legacy-upgrade`: Enable legacy contract upgrade behavior + - `--scheduled-transactions`: Enable scheduled transactions (default true) + - `--script-gas-limit `: Gas limit for scripts (default `100000`) + - `--transaction-max-gas-limit `: Max transaction gas limit (default `9999`) + - `--transaction-expiry `: Transaction expiry in blocks (default `10`) + - `--skip-tx-validation`: Skip tx signature and sequence number checks + - `--simple-addresses`: Use sequential addresses starting with `0x01` + - `--storage-limit`: Enforce account storage limit (default true) + - `--storage-per-flow `: MB of storage per 1 FLOW token + - `--token-supply `: Initial FLOW token supply (default `1000000000.0`) + - `--transaction-fees`: Enable transaction fees + - `--setup-evm`: Deploy EVM contracts (default true) + - `--setup-vm-bridge`: Deploy VM Bridge contracts (default true) + +- **Service Account & Identity** + - `--chain-id `: Address generation chain (default `emulator`) + - `--service-priv-key ` / `--service-pub-key `: Service account keys + - `--service-sig-algo `: Service key signature algo (default `ECDSA_P256`) + - `--service-hash-algo `: Service key hash algo (default `SHA3_256`) + - `--min-account-balance `: Minimum account balance / account creation cost + - `--contracts`: Deploy common contracts on start + - `--contract-removal`: Allow contract removal for development (default true) + - `--init`: Initialize a new account profile + +- **Logging & Output** + - `--verbose, -v`: Verbose logging + - `--log-format `: Logging output format (default `text`) + +- **Snapshots** + - `--snapshot`: Enable snapshots in the emulator + +## Examples ```bash -# Start with verbose logging +# Verbose logs flow emulator --verbose -# Set custom block time (e.g., 1 second between blocks) +# Custom ports +flow emulator --port 9000 --rest-port 9001 --admin-port 9002 + +# Custom block time (1 second between blocks) flow emulator --block-time 1s -# Persist state between restarts -flow emulator --persist +# Persist state on disk +flow emulator --persist --dbpath ./flowdb + +# Fork from Testnet at a specific height +flow emulator --rpc-host access.devnet.nodes.onflow.org:9000 --start-block-height 12345678 + +# Disable fees and use simple addresses for local testing +flow emulator --transaction-fees=false --simple-addresses + +# Enable code coverage reporting +flow emulator --coverage-reporting ``` -For all available options, see the [CLI commands overview](../flow-cli/index.md). +For the complete and current list of flags, run: + +```bash +flow emulator --help +``` ## Debugging & Testing From a2d3884b2ee6fc7d376ba7d44e3c769f516adfbb Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Thu, 23 Oct 2025 12:32:29 -0700 Subject: [PATCH 02/23] Add fork testing tutorial --- .../cadence/fork-testing/index.md | 531 ++++++++++++++++++ docs/build/cadence/smart-contracts/testing.md | 124 ++++ docs/build/tools/flow-cli/tests.md | 55 ++ docs/protocol/flow-networks/index.md | 4 + 4 files changed, 714 insertions(+) create mode 100644 docs/blockchain-development-tutorials/cadence/fork-testing/index.md diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md new file mode 100644 index 0000000000..71baa61204 --- /dev/null +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -0,0 +1,531 @@ +--- +sidebar_position: 20 +sidebar_label: Fork Testing +title: Fork Testing with Cadence +description: Run your Cadence test suite against a forked mainnet or testnet using flow test --fork. Test against real contracts and production data without deploying to live networks. +keywords: + - fork testing + - flow test + - cadence tests + - mainnet fork + - testnet fork + - integration testing + - Flow CLI + - account impersonation + - production testing +--- + +# Fork Testing with Cadence + +This tutorial teaches you how to run your Cadence tests against a snapshot of Flow mainnet or testnet using `flow test --fork`. You'll learn how to test your contracts against real deployed contracts and production data without needing to deploy anything to a live network or bootstrap test accounts. + +Fork testing bridges the gap between fast local unit tests and expensive testnet deployments. It enables you to validate your contracts work correctly with real on-chain state, test integrations with deployed contracts, and debug issues using historical blockchain data—all in a safe, local environment. + +## What You'll Learn + +After completing this tutorial, you'll be able to: + +- **Run Cadence tests against forked networks** using `flow test --fork` +- **Test contracts that depend on real mainnet contracts** without manual setup +- **Use account impersonation** to execute transactions as any mainnet account +- **Read from production blockchain state** in your test suite +- **Pin tests to specific block heights** for historical debugging +- **Integrate fork testing** into your development workflow + +## What You'll Build + +You'll create a complete fork testing setup that demonstrates: + +- Reading from the live FlowToken contract on mainnet +- Deploying your own contract that interacts with mainnet contracts +- Testing custom logic against real account balances and state +- Executing transactions using impersonated mainnet accounts +- A reusable pattern for integration testing your Flow applications + +**Time Commitment:** Approximately 30 minutes + +## Prerequisites + +### Flow CLI + +This tutorial requires [Flow CLI] v1.8.0 or later installed. If you haven't installed it yet and have [homebrew] installed, run: + +```bash +brew install flow-cli +``` + +For other operating systems, refer to the [installation guide]. + +### Basic Cadence Testing Knowledge + +You should be familiar with writing basic Cadence tests. If you're new to Cadence testing, start with [Testing Smart Contracts] first. + +### Network Access + +You'll need network access to Flow's public access nodes. The tutorial uses these endpoints, which are freely available: + +- Mainnet: `access.mainnet.nodes.onflow.org:9000` +- Testnet: `access.devnet.nodes.onflow.org:9000` + +:::info + +This tutorial covers `flow test --fork` (running tests against forked network state), which is different from `flow emulator --fork` (starting the emulator in fork mode for manual interaction). + +::: + +## Create Your Project + +Navigate to your development directory and create a new Flow project: + +```zsh +mkdir fork-testing-demo +cd fork-testing-demo +flow init --yes +``` + +The `--yes` flag accepts defaults non-interactively. `flow init` is interactive by default and can scaffold various templates. + +Alternatively, create the directory and initialize in one command: + +```zsh +flow init fork-testing-demo --yes +cd fork-testing-demo +``` + +## Install Dependencies + +Use the [Dependency Manager] to install the `FlowToken` and `FungibleToken` contracts: + +```zsh +flow dependencies install FlowToken FungibleToken +``` + +This downloads the contracts and their dependencies into the `imports/` folder and updates your `flow.json` with the correct addresses and aliases across all networks (mainnet, testnet, emulator). + +Your `flow.json` will now include an entry like: + +```json +{ + "dependencies": { + "FlowToken": { + "source": "mainnet://1654653399040a61.FlowToken", + "aliases": { + "emulator": "0ae53cb6e3f42a79", + "mainnet": "1654653399040a61", + "testnet": "7e60df042a9c0868" + } + } + } +} +``` + +Your `flow.json` should now have the mainnet and testnet networks configured from `flow init`. In fork mode, contract imports automatically resolve to the correct network addresses. + +## Test Reading Live State + +Create the test directories: + +```zsh +mkdir -p tests cadence/scripts +``` + +First, create a script to read FlowToken supply. Create `cadence/scripts/GetFlowTokenSupply.cdc`: + +```cadence cadence/scripts/GetFlowTokenSupply.cdc +import "FlowToken" + +access(all) fun main(): UFix64 { + return FlowToken.totalSupply +} +``` + +Now create the test file `tests/flow_token_test.cdc`: + +```cadence tests/flow_token_test.cdc +import Test + +access(all) fun testFlowTokenSupplyIsPositive() { + let scriptResult = Test.executeScript( + Test.readFile("cadence/scripts/GetFlowTokenSupply.cdc"), + [] + ) + + Test.expect(scriptResult, Test.beSucceeded()) + + let supply = scriptResult.returnValue! as! UFix64 + Test.assert(supply > 0.0, message: "FlowToken supply should be positive") +} +``` + +Notes: +- Use `Test.executeScript()` to read contract state +- The script imports `FlowToken` by name - the dependency manager handles address resolution +- In fork mode, this automatically uses the mainnet FlowToken contract +- Extract the return value with proper type casting and assert on it + +#### Quick verify + +Run just this test file against a fork to confirm your setup works: + +```zsh +flow test tests/flow_token_test.cdc --fork +``` + +Target testnet instead: + +```zsh +flow test tests/flow_token_test.cdc --fork testnet +``` + +You should see the test PASS. If not, verify your network host in `flow.json` and that dependencies are installed. + +## Deploy and Test Your Contract + +Now you'll create a contract that depends on FlowToken and test it against the forked mainnet state—no need to bootstrap tokens or set up test accounts. + +### Create a Test Account + +Create a mainnet account for testing: + +```zsh +flow accounts create +``` + +When prompted, select `mainnet` as the network. This will generate a new account and save the private key to a `.pkey` file. Note the account address (e.g., `0xf8d6e0586b0a20c7`). + +### Create a Contract that Uses FlowToken + +Generate a new contract: + +```zsh +flow generate contract TokenChecker +``` + +This creates `cadence/contracts/TokenChecker.cdc` and adds it to `flow.json`. Now update the contract with your logic: + +```cadence cadence/contracts/TokenChecker.cdc +import "FlowToken" + +access(all) contract TokenChecker { + + access(all) fun checkBalance(address: Address): UFix64 { + let account = getAccount(address) + + let vaultRef = account.capabilities + .borrow<&FlowToken.Vault>(/public/flowTokenBalance) + ?? panic("Could not borrow FlowToken Vault reference") + + return vaultRef.balance + } + + access(all) fun hasMinimumBalance(address: Address, minimum: UFix64): Bool { + return self.checkBalance(address: address) >= minimum + } +} +``` + +### Configure Contract Deployment + +Add the deployment configuration to `flow.json`. Replace `YOUR_ACCOUNT_ADDRESS` with the address from the previous step: + +```json +{ + "contracts": { + "TokenChecker": { + "source": "cadence/contracts/TokenChecker.cdc" + } + }, + "deployments": { + "mainnet": { + "mainnet-account": ["TokenChecker"] + } + }, + "accounts": { + "mainnet-account": { + "address": "YOUR_ACCOUNT_ADDRESS", + "key": "$PRIVATE_KEY" + } + } +} +``` + +This configuration tells the test framework to deploy `TokenChecker` to your mainnet account when running fork tests. + +### Create Scripts for Testing + +Create `cadence/scripts/CheckBalance.cdc`: + +```cadence cadence/scripts/CheckBalance.cdc +import "TokenChecker" + +access(all) fun main(addr: Address): UFix64 { + return TokenChecker.checkBalance(address: addr) +} +``` + +Create `cadence/scripts/HasMinimumBalance.cdc`: + +```cadence cadence/scripts/HasMinimumBalance.cdc +import "TokenChecker" + +access(all) fun main(addr: Address, min: UFix64): Bool { + return TokenChecker.hasMinimumBalance(address: addr, minimum: min) +} +``` + +### Test Your Contract with Forked State + +Create `tests/token_checker_test.cdc`: + +```cadence tests/token_checker_test.cdc +import Test + +access(all) fun setup() { + // Deploy TokenChecker to the test account + let err = Test.deployContract( + name: "TokenChecker", + path: "cadence/contracts/TokenChecker.cdc", + arguments: [] + ) + Test.expect(err, Test.beNil()) +} + +access(all) fun testCheckBalanceOnRealAccount() { + // Test against a real mainnet account (Flow service account) + let scriptResult = Test.executeScript( + Test.readFile("cadence/scripts/CheckBalance.cdc"), + [0x1654653399040a61] // Flow service account on mainnet + ) + + Test.expect(scriptResult, Test.beSucceeded()) + + let balance = scriptResult.returnValue! as! UFix64 + // The Flow service account should have a balance + Test.assert(balance > 0.0, message: "Service account should have FLOW tokens") +} + +access(all) fun testHasMinimumBalance() { + let scriptResult = Test.executeScript( + Test.readFile("cadence/scripts/HasMinimumBalance.cdc"), + [0x1654653399040a61, 1000.0] + ) + + Test.expect(scriptResult, Test.beSucceeded()) + + let hasMinimum = scriptResult.returnValue! as! Bool + Test.assert(hasMinimum == true, message: "Service account should have at least 1000 FLOW") +} +``` + +### What's Happening Here + +1. **Your contract uses FlowToken**: `TokenChecker` imports and interacts with the real FlowToken contract +2. **No bootstrapping needed**: When you run with `--fork`, real mainnet accounts (like `0x1654653399040a61`, the Flow service account) already have balances +3. **Test against real state**: You can query actual accounts and verify your contract logic works with production data +4. **Local deployment**: Your `TokenChecker` contract is deployed locally to the test environment, but it reads from forked mainnet state + +## Execute Transactions with Account Impersonation + +Fork testing includes built-in account impersonation—you can execute transactions as **any mainnet account** without needing private keys. This lets you test interactions with real accounts and their existing state. + +### Create Transactions + +Create the transactions directory: + +```zsh +mkdir -p cadence/transactions +``` + +First, create a transaction to set up a FlowToken vault. Create `cadence/transactions/SetupFlowTokenVault.cdc`: + +```cadence cadence/transactions/SetupFlowTokenVault.cdc +import "FungibleToken" +import "FlowToken" + +transaction { + prepare(signer: &Account) { + if signer.storage.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault) == nil { + signer.storage.save(<-FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>()), to: /storage/flowTokenVault) + let cap = signer.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault) + signer.capabilities.publish(cap, at: /public/flowTokenReceiver) + signer.capabilities.publish(cap, at: /public/flowTokenBalance) + } + } +} +``` + +Now create the transfer transaction. Create `cadence/transactions/TransferTokens.cdc`: + +```cadence cadence/transactions/TransferTokens.cdc +import "FungibleToken" +import "FlowToken" + +transaction(amount: UFix64, to: Address) { + let sentVault: @{FungibleToken.Vault} + + prepare(signer: &Account) { + let vaultRef = signer.storage.borrow( + from: /storage/flowTokenVault + ) ?? panic("Could not borrow reference to the owner's Vault") + + self.sentVault <- vaultRef.withdraw(amount: amount) + } + + execute { + let recipient = getAccount(to) + let receiverRef = recipient.capabilities + .borrow<&{FungibleToken.Receiver}>(/public/flowTokenReceiver) + ?? panic("Could not borrow receiver reference") + + receiverRef.deposit(from: <-self.sentVault) + } +} +``` + +### Test Transaction Execution with Impersonation + +Add this test function to the existing `tests/token_checker_test.cdc` file: + +```cadence +access(all) fun testTransactionAsMainnetAccount() { + // Impersonate the Flow service account (or any mainnet account) + // No private keys needed - fork testing has built-in impersonation + let serviceAccount = Test.getAccount(0x1654653399040a61) + + // Check initial balance + let initialBalanceScript = Test.executeScript( + Test.readFile("cadence/scripts/CheckBalance.cdc"), + [serviceAccount.address] + ) + Test.expect(initialBalanceScript, Test.beSucceeded()) + let initialBalance = initialBalanceScript.returnValue! as! UFix64 + + // Create a test recipient account and set up FlowToken vault + let recipient = Test.createAccount() + + // Set up the recipient's FlowToken vault + let setupResult = Test.executeTransaction( + Test.Transaction( + code: Test.readFile("cadence/transactions/SetupFlowTokenVault.cdc"), + authorizers: [recipient.address], + signers: [recipient], + arguments: [] + ) + ) + Test.expect(setupResult, Test.beSucceeded()) + + // Execute transaction AS the mainnet service account + // This works because fork testing allows impersonating any account + let txResult = Test.executeTransaction( + Test.Transaction( + code: Test.readFile("cadence/transactions/TransferTokens.cdc"), + authorizers: [serviceAccount.address], + signers: [serviceAccount], + arguments: [10.0, recipient.address] + ) + ) + + Test.expect(txResult, Test.beSucceeded()) + + // Verify the sender's balance decreased + let newBalanceScript = Test.executeScript( + Test.readFile("cadence/scripts/CheckBalance.cdc"), + [serviceAccount.address] + ) + Test.expect(newBalanceScript, Test.beSucceeded()) + let newBalance = newBalanceScript.returnValue! as! UFix64 + + // Balance should have decreased by exactly the transfer amount + Test.assertEqual(initialBalance - 10.0, newBalance) + + // Verify the recipient received the tokens + let recipientBalanceScript = Test.executeScript( + Test.readFile("cadence/scripts/CheckBalance.cdc"), + [recipient.address] + ) + Test.expect(recipientBalanceScript, Test.beSucceeded()) + let recipientBalance = recipientBalanceScript.returnValue! as! UFix64 + Test.assertEqual(10.0, recipientBalance) +} +``` + +### Key Points About Account Impersonation + +1. **Any account can be used**: Call `Test.getAccount(address)` with any mainnet address +2. **No private keys needed**: Fork testing has built-in impersonation—you can sign transactions as any account +3. **Real account state**: The account has its actual mainnet balance, storage, and capabilities +4. **Mutations are local**: Changes only affect your test environment, not the real network +5. **Test complex scenarios**: Impersonate whale accounts, protocol accounts, or any user to test edge cases + +## Run All Tests Together + +Now that you have multiple test files, run them all against the forked network: + +```zsh +flow test --fork +``` + +This runs all `*_test.cdc` files in your project against mainnet by default. You should see: + +``` +Test results: "tests/flow_token_test.cdc" +- PASS: testFlowTokenSupplyIsPositive + +Test results: "tests/token_checker_test.cdc" +- PASS: testCheckBalanceOnRealAccount +- PASS: testHasMinimumBalance +- PASS: testTransactionAsMainnetAccount +``` + +### Additional Options + +You can also fork from testnet (`flow test --fork testnet`) or pin to a specific block height (`--fork-height`). See the [Fork Testing Flags] reference for all available options. + +## When to Use Fork Testing + +Fork testing is most valuable for: + +- Integration testing with real onchain contracts and data +- Pre-deployment validation before mainnet releases +- Upgrade testing against production state +- Reproducing issues at a specific block height +- Testing interactions with high-value or protocol accounts +- Validating contract behavior with real-world data patterns + +For strategy, limitations, and best practices, see the guide: [Testing Smart Contracts]. + +## Conclusion + +In this tutorial, you learned how to use fork testing to validate your Cadence contracts against live Flow network state. You created tests that read from real mainnet contracts, deployed custom contracts that interact with production data, and executed transactions using account impersonation—all without deploying to a live network or bootstrapping test accounts. + +Now that you have completed this tutorial, you should be able to: + +- **Run Cadence tests against forked networks** using `flow test --fork` +- **Test contracts that depend on real mainnet contracts** without manual setup +- **Use account impersonation** to execute transactions as any mainnet account +- **Read from production blockchain state** in your test suite +- **Pin tests to specific block heights** for historical debugging +- **Integrate fork testing** into your development workflow + +Fork testing bridges the gap between local unit tests and testnet deployments, enabling you to catch integration issues early and test against real-world conditions. Use it as part of your pre-deployment validation process, alongside unit tests for speed and testnet deployments for final verification. + +### Next Steps + +- Explore additional assertions and helpers in the [Cadence Testing Framework] +- Add more real-world tests that read from standard contracts like Flow NFT +- Keep unit tests on the emulator for speed and run forked integration tests selectively in CI +- Review the [Fork Testing Flags] reference for advanced options +- Learn about [Flow Networks] and public access nodes + + + +[Flow CLI]: ../../../build/tools/flow-cli/index.md +[homebrew]: https://brew.sh +[installation guide]: ../../../build/tools/flow-cli/install.md +[Testing Smart Contracts]: ../../../build/cadence/smart-contracts/testing.md +[Dependency Manager]: ../../../build/tools/flow-cli/dependency-manager.md +[Fork Testing Flags]: ../../../build/tools/flow-cli/tests.md#fork-testing-flags +[Cadence Testing Framework]: https://cadence-lang.org/docs/testing-framework +[Flow Networks]: ../../../protocol/flow-networks/index.md + + diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index a5bc94b050..5d3d593405 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -259,6 +259,130 @@ There is also a [repository](https://github.com/m-Peter/flow-code-coverage#readm The Cadence testing framework utilizes the emulator under the hood. +### Fork Testing + +Fork testing lets you run your Cadence test files (`*_test.cdc`) against a snapshot of a live Flow network (mainnet or testnet). This enables realistic integration tests that read real contract code and on-chain state while keeping all mutations local to your test run. + + +This section covers `flow test --fork` (running tests against a forked network), which is different from `flow emulator --fork` (starting the emulator in fork mode for manual interaction). + + +#### What is fork testing? + +When you run tests with the `--fork` flag, the test runner: + +- Connects to a Flow access node (public or custom) +- Fetches account state, contract code, and other data on demand +- Executes your tests as if they are running against the live network state +- Keeps all state changes local to your test process (the real network is never mutated) + +This bridges the gap between fast, purely local tests and deploying to testnet/mainnet for validation. + +#### Quick start + +Example: Read from the real FlowToken contract on mainnet. + +```cadence flow_token_test.cdc +import Test +import "FlowToken" // Resolves to mainnet alias when running with --fork + +access(all) fun testFlowTokenSupplyIsPositive() { + let supply = FlowToken.totalSupply + Test.assert(supply > 0.0, message: "FlowToken supply should be positive") +} +``` + +Ensure your `flow.json` defines the mainnet alias for `FlowToken`: + +```json +{ + "contracts": { + "FlowToken": { + "source": "./cadence/contracts/FlowToken.cdc", + "aliases": { + "mainnet": "0x1654653399040a61" + } + } + }, + "networks": { + "mainnet": { + "host": "access.mainnet.nodes.onflow.org:9000" + } + } +} +``` + +Run the test against a fork of mainnet: + +```bash +flow test --fork +``` + +To target testnet instead: + +```bash +flow test --fork testnet +``` + +#### Common use cases + +- Integration testing with real contracts (NFT marketplaces, DEXs, core contracts) +- Pre-deployment validation against production data +- Upgrade testing with production state +- Historical debugging with a specific block height + +Examples: + +```bash +# Run a single test file against mainnet +flow test tests/my_marketplace_test.cdc --fork mainnet + +# Pin to a specific block height for historical state +flow test --fork mainnet --fork-height 85432100 + +# Generate coverage while forking +flow test --fork --cover +``` + +#### How contract aliases are resolved + +- Normal mode (no `--fork`): your imports use the `testing` aliases from `flow.json` (for emulator deployments) +- Fork mode: imports automatically use the aliases for the selected network (e.g. `mainnet` or `testnet`) defined in `flow.json` + +This means you typically do not need to change imports in your test code when switching between local and forked runs—configure aliases once and select the mode via flags. + +#### Limitations and considerations + +- Network performance: tests may run slower than local emulator tests due to network calls +- Point-in-time snapshot: forked state reflects the time of query (or the specified `--fork-height`), not a live stream +- Read-only network: mutations in your tests are local and do not affect the real network +- Spork boundaries: access nodes only retain historical data for the current spork; pinning via `--fork-height` cannot reach beyond that boundary. Learn more about the Flow spork process in the Network Upgrade (Spork) docs. + +See: [Network Upgrade (Spork) Process](../../../protocol/node-ops/node-operation/network-upgrade.md) + +#### Best practices + +1. Use fork testing primarily for integration tests; keep unit tests on the emulator for speed +2. Keep forked tests separate in CI and run them selectively +3. Prefer testnet before mainnet to catch network-specific issues with fewer risks +4. Document dependencies on specific mainnet/testnet contracts and addresses +5. Consider real data requirements—fork testing shines when reading existing on-chain state + +#### Commands reference + +See the flag reference for available options and details. + +Guide → Tutorial: [Fork Testing with Cadence (Step-by-Step)](../../../blockchain-development-tutorials/cadence/fork-testing/index.md) + +Guide → Flags: [Fork Testing Flags](../../../build/tools/flow-cli/tests.md#fork-testing-flags) + +```bash +flow test --fork # Fork from mainnet (default when value omitted) +flow test --fork testnet # Fork from testnet +flow test --fork --cover # With coverage report +flow test --fork --fork-height NUM # Pin to block height +``` + ### Go Tests Tests in Go can be written using [flow-go-sdk](https://github.com/onflow/flow-go-sdk) and the go test command. diff --git a/docs/build/tools/flow-cli/tests.md b/docs/build/tools/flow-cli/tests.md index 369d812cac..3e1b9f7ea3 100644 --- a/docs/build/tools/flow-cli/tests.md +++ b/docs/build/tools/flow-cli/tests.md @@ -225,3 +225,58 @@ flow test --name=testSumOfTwo This command will run only the test function named `testSumOfTwo` across all test scripts that contain it. To dive deeper into testing the functionality of your Cadence scripts and contracts, explore the [Cadence Testing Framework](https://cadence-lang.org/docs/testing-framework) documentation. + +--- + +### Fork Testing Flags + +Run tests against forked mainnet or testnet state. For a step-by-step tutorial, see: [Fork Testing with Cadence](../../../blockchain-development-tutorials/cadence/fork-testing/index.md). For background and best practices, see the guide: [Fork Testing](../../cadence/smart-contracts/testing.md#fork-testing). + +#### --fork + +- Type: `string` +- Default: `""` (empty). If provided without a value, defaults to `mainnet`. + +Fork tests from a network defined in `flow.json`. The CLI resolves the GRPC access host and chain ID from the selected network configuration. + +```shell +flow test --fork # Uses mainnet by default +flow test --fork testnet # Uses testnet +flow test --fork mynet # Uses a custom network defined in flow.json +``` + +Requirements: + +- The network must exist in `flow.json` +- The network must have a valid `host` configured + +Common errors: + +- `network "" not found in flow.json` → add the network definition +- `network "" has no host configured` → set the `host` field + +#### --fork-host + +- Type: `string` +- Default: `""` + +Directly specify a GRPC access node host. This bypasses the `flow.json` network lookup. + +```shell +flow test --fork-host access.mainnet.nodes.onflow.org:9000 +``` + +See public access node URLs in [Flow Networks](../../../protocol/flow-networks/index.md). + +#### --fork-height + +- Type: `uint64` +- Default: `0` + +Pin the fork to a specific block height for historical state testing. Only data from the current spork is available via public access nodes. + +```shell +flow test --fork mainnet --fork-height 85432100 +``` + +> Note: Historical data beyond spork boundaries is not available via standard access nodes. See the [Network Upgrade (Spork) Process](../../../protocol/node-ops/node-operation/network-upgrade.md). diff --git a/docs/protocol/flow-networks/index.md b/docs/protocol/flow-networks/index.md index 4c23c8420f..dc41cf216a 100644 --- a/docs/protocol/flow-networks/index.md +++ b/docs/protocol/flow-networks/index.md @@ -27,6 +27,10 @@ For more information on how to access these networks, refer to the following gui - [Flow Testnet](./accessing-testnet.md) - [Flow Mainnet](./accessing-mainnet.md) + +You can use these public GRPC hosts directly with forked tests via `flow test --fork-host `. See the CLI reference: [Fork Testing Flags](../../build/tools/flow-cli/tests.md#fork-testing-flags). + + ### Network There are two primary ways to access onchain data within the Flow network; Access Nodes and Light nodes. Access Nodes are the node type that are most useful for developers, as they provide access to the Flow network via the following API endpoints: From b24975ac9a69227a4b6e54a805c75d7caf666520 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 06:29:10 -0700 Subject: [PATCH 03/23] update positioning --- .../cadence/fork-testing/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index 71baa61204..f55439849a 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -17,9 +17,9 @@ keywords: # Fork Testing with Cadence -This tutorial teaches you how to run your Cadence tests against a snapshot of Flow mainnet or testnet using `flow test --fork`. You'll learn how to test your contracts against real deployed contracts and production data without needing to deploy anything to a live network or bootstrap test accounts. +This tutorial teaches you how to run your Cadence tests against a snapshot of Flow mainnet using `flow test --fork`. You'll learn how to test your contracts against real deployed contracts and production data without needing to deploy anything to a live network or bootstrap test accounts. -Fork testing bridges the gap between fast local unit tests and expensive testnet deployments. It enables you to validate your contracts work correctly with real on-chain state, test integrations with deployed contracts, and debug issues using historical blockchain data—all in a safe, local environment. +Fork testing bridges the gap between isolated local unit tests and testnet deployments. It enables you to validate your contracts work correctly with real on-chain state, test integrations with deployed contracts, and debug issues using historical blockchain data—all in a safe, local environment. ## What You'll Learn @@ -507,13 +507,13 @@ Now that you have completed this tutorial, you should be able to: - **Pin tests to specific block heights** for historical debugging - **Integrate fork testing** into your development workflow -Fork testing bridges the gap between local unit tests and testnet deployments, enabling you to catch integration issues early and test against real-world conditions. Use it as part of your pre-deployment validation process, alongside unit tests for speed and testnet deployments for final verification. +Fork testing bridges the gap between local unit tests and testnet deployments, enabling you to catch integration issues early and test against real-world conditions. Use it as part of your pre-deployment validation process, alongside emulator unit tests for determinism and isolation, and testnet deployments for final verification. ### Next Steps - Explore additional assertions and helpers in the [Cadence Testing Framework] - Add more real-world tests that read from standard contracts like Flow NFT -- Keep unit tests on the emulator for speed and run forked integration tests selectively in CI +- Keep unit tests on the emulator for determinism and isolation; run forked integration tests selectively in CI - Review the [Fork Testing Flags] reference for advanced options - Learn about [Flow Networks] and public access nodes From 6f3e7b14afcab5aafa9c03662a11ea0b41487a3e Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 07:13:31 -0700 Subject: [PATCH 04/23] Add high level testing strategy doc and update fork tutorial --- .../cadence/fork-testing/index.md | 47 ++++++- .../smart-contracts/testing-strategy.md | 128 ++++++++++++++++++ docs/build/cadence/smart-contracts/testing.md | 18 ++- docs/build/tools/emulator/index.md | 1 + docs/build/tools/flow-cli/tests.md | 8 +- 5 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 docs/build/cadence/smart-contracts/testing-strategy.md diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index f55439849a..3b3564fd82 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -44,6 +44,16 @@ You'll create a complete fork testing setup that demonstrates: **Time Commitment:** Approximately 30 minutes +### Reproducibility first + +Pin a specific block height when you need reproducible results: + +```zsh +flow test --fork mainnet --fork-height +``` + +Document the pin heights you rely on (for example in CI variables or a simple file in the repo) and update them via a dedicated freshness PR. For best results, keep a per‑spork stable pin and also run a "latest" freshness job. + ## Prerequisites ### Flow CLI @@ -226,7 +236,7 @@ access(all) contract TokenChecker { ### Configure Contract Deployment -Add the deployment configuration to `flow.json`. Replace `YOUR_ACCOUNT_ADDRESS` with the address from the previous step: +Add the deployment configuration to `flow.json`. The account you created in the previous step is already present under `accounts`; reference it here: ```json { @@ -242,8 +252,8 @@ Add the deployment configuration to `flow.json`. Replace `YOUR_ACCOUNT_ADDRESS` }, "accounts": { "mainnet-account": { - "address": "YOUR_ACCOUNT_ADDRESS", - "key": "$PRIVATE_KEY" + "address": "", + "key": "" } } } @@ -481,6 +491,37 @@ Test results: "tests/token_checker_test.cdc" You can also fork from testnet (`flow test --fork testnet`) or pin to a specific block height (`--fork-height`). See the [Fork Testing Flags] reference for all available options. +See also: + +- High-Level Testing Strategy: [Testing Strategy on Flow](../../../build/cadence/smart-contracts/testing-strategy.md) +- Emulator (fork mode for interactive E2E): [Flow Emulator](../../../build/tools/emulator/index.md) +- Networks and access nodes: [Flow Networks](../../../protocol/flow-networks/index.md) + +::::info +External oracles and off-chain systems + +Fork tests run against Flow chain state only: +- No live off-chain/API calls or cross-chain reads +- Price feeds, bridges, indexers, and similar must be mocked (stub contracts or fixtures) +- For end-to-end, combine with `flow emulator --fork` and a local stub service +:::: + +### Select tests quickly + +- Run specific files or directories: + +```zsh +flow test tests/flow_token_test.cdc tests/token_checker_test.cdc tests/subsuite/ +``` + +- Optional: narrow by function name with `--name`: + +```zsh +flow test tests/token_checker_test.cdc --name _smoke +``` + +- Optional: suffix a few functions with `_smoke` for quick PR runs; run the full suite nightly or on protected branches. + ## When to Use Fork Testing Fork testing is most valuable for: diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md new file mode 100644 index 0000000000..8e847fe2a1 --- /dev/null +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -0,0 +1,128 @@ +--- +title: Testing Strategy on Flow +sidebar_label: Testing Strategy +sidebar_position: 3 +description: A layered testing strategy for Flow—emulator unit/property tests, forked integration, emulator fork sandbox, testnet canaries, and post-deploy monitoring. Guidance for reproducibility, CI selection, and triage. +keywords: + - testing strategy + - fork testing + - emulator + - CI + - reproducibility + - pins + - Flow CLI + - Cadence tests +--- + +# Testing Strategy on Flow + +A single, pragmatic strategy for testing on Flow. Use layers that are deterministic and isolated by default, add realism with forks when needed, and keep a minimal set of live network checks before release. + +## At a glance + +- **Unit & Property (emulator, no fork)**: Hermetic correctness and invariants +- **Integration (automated, `flow test --fork`)**: Real contracts and data; mutations stay local +- **Local integration sandbox (interactive, `flow emulator --fork`)**: Drive apps/E2E against production-like state +- **Staging (testnet)**: Final plumbing and config checks +- **Post-deploy (read-only)**: Invariant dashboards and alerts + +## Layers + +### Unit & Property (Emulator, no fork) + +- **Use when**: Validating Cadence logic, invariants, access control, error paths, footprint +- **Why**: Fully deterministic and isolated; highest-regression signal +- **Run**: Every commit/PR; wide parallelism +- **Notes**: Favor property/invariant checks and fuzzing; zero external dependencies + +### Integration (Automated) — `flow test --fork` + +- **Use when**: Interacting with real on-chain contracts/data (FT/NFT standards, AMMs, wallets, oracles, bridges), upgrade checks, historical repro +- **Why**: Real addresses, capability paths, and resource schemas; catches drift early + - **Run**: PRs may run the full forked suite (pinned) or a small smoke subset; broader matrix nightly/on merge +- **Notes**: + - Pin with `--fork-height` where reproducibility matters + - Prefer local deployment + impersonation over real mainnet accounts + - Mutations are local to the forked runtime; the live network is never changed + - Be mindful of access-node availability and rate limits + - External oracles/protocols: forked tests do not call off-chain services or other chains; mock these or run a local stub + +### Local Integration Sandbox (Interactive) — `flow emulator --fork` + +- **Use when**: Driving dapps, wallets, bots, indexers, or exploratory debugging outside the test framework +- **Why**: Production-like state with local, disposable control; great for E2E and migrations +- **Run**: Dev machines and focused E2E CI jobs +- **Notes**: Pin height; run on dedicated ports; impersonation is built-in; mutations are local; off-chain/oracle calls are not live—mock or run local stubs + +### Staging — Testnet + +- **Use when**: Final network plumbing and configuration checks before release +- **Why**: Validates infra differences you cannot fully simulate +- **Run**: Pre-release and on infra changes +- **Notes**: Keep canaries minimal and time-boxed; protocol/partner support may be limited on testnet (not all third-party contracts are deployed or up to date) + +### Post-deploy Monitoring (read-only) + +- **Use when**: After releases to confirm invariants and event rates +- **Why**: Detects real-world anomalies quickly +- **Run**: Continuous dashboards/alerts tied to invariants + +## Reproducibility and data management + + - **Pin where reproducibility matters**: Use `--fork-height ` for both `flow test --fork` and `flow emulator --fork`. Pins are per‑spork; historical data beyond spork boundaries is unavailable. For best results, keep a per‑spork stable pin and also run a "latest" freshness job. +- **Named snapshots**: Maintain documented pin heights (e.g., in CI vars or a simple file) with names per dependency/protocol +- **Refresh policy**: Advance pins via a dedicated “freshness” PR; compare old vs. new pins +- **Goldens**: Save a few canonical samples (e.g., event payloads, resource layouts, key script outputs) as JSON in your repo, and compare them in CI to catch accidental schema/shape changes. Update the samples intentionally as part of upgrades. + +## CI tips + +- PRs: Run emulator unit/property and forked integration (pinned). Full suite is fine if practical; otherwise a small smoke set. +- Nightly/Main: Add a latest pin job and a broader fork matrix when needed. +- E2E (optional): Use `flow emulator --fork` at a stable pin and run your browser tests. + +## Test selection and tagging + + - **Optional naming helpers**: Use simple suffixes in test names like `_fork`, `_smoke`, `_e2e` if helpful + - Run the tests you care about by passing files/directories: `flow test FILE1 FILE2 DIR1 ...` (most common) + - Optionally, use `--name ` to match test functions when it’s convenient +- **Defaults**: PRs can run the full fork suite (pinned) or a small smoke set; nightly runs the full matrix (+ optional E2E) + +## Triage tips + +- Re-run at the same `--fork-height`, then at latest +- Compare contract addresses/aliases in `flow.json` +- Diff event/resource shapes against your stored samples +- Check access-node health and CI parallelism/sharding + +## Handy commands + +```bash +# Unit/property (emulator) +flow test + +# Forked integration (pinned) +flow test --fork mainnet --fork-height + +# Local sandbox (interactive) +flow emulator --fork mainnet --fork-height +``` + +## Do / Don’t + +- **Do**: Keep a fast, hermetic base; pin forks; tag tests; maintain tiny PR smoke sets; document pins and set a simple refresh schedule (e.g., after each spork or monthly) +- **Don’t**: Make “latest” your default in CI; create or rely on real mainnet accounts; conflate `flow test --fork` with `flow emulator --fork` + +## Related docs + +- Guide → Running tests: [Running Cadence Tests](../../tools/flow-cli/tests.md) +- Guide → Background: [Testing Smart Contracts](./testing.md) +- Tutorial → Step-by-step: [Fork Testing with Cadence](../../../blockchain-development-tutorials/cadence/fork-testing/index.md) +- Tool → Emulator (including fork mode): [Flow Emulator](../../tools/emulator/index.md) +- Flags → `flow test --fork`: [Fork Testing Flags](../../tools/flow-cli/tests.md#fork-testing-flags) +- Networks → Public access nodes: [Flow Networks](../../../protocol/flow-networks/index.md) +- Upgrades → Spork boundaries: [Network Upgrade (Spork) Process](../../../protocol/node-ops/node-operation/network-upgrade.md) +- Config → Network and hosts: [Flow CLI Configuration (flow.json)](../../tools/flow-cli/flow.json/initialize-configuration.md) +- Imports → Resolving aliases: [Dependency Manager](../../tools/flow-cli/dependency-manager.md) +- Language → Assertions & helpers: [Cadence Testing Framework](https://cadence-lang.org/docs/testing-framework) + + diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index 5d3d593405..e02baa5905 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -27,6 +27,8 @@ keywords: Testing is an essential part of smart contract development to ensure the correctness and reliability of your code. The Cadence Testing Framework provides a convenient way to write tests for your contracts, scripts and transactions which allows you to verify the functionality and correctness of your smart contracts. +> For a layered approach to when and why to use emulator, forked integration, and testnet, see the strategy guide: [Testing Strategy on Flow](./testing-strategy.md). + ## Install Flow CLI The [Flow CLI](../../../build/tools/flow-cli/index.md) is the primary tool for developing, testing, and deploying smart contracts to the Flow network. @@ -276,7 +278,7 @@ When you run tests with the `--fork` flag, the test runner: - Executes your tests as if they are running against the live network state - Keeps all state changes local to your test process (the real network is never mutated) -This bridges the gap between fast, purely local tests and deploying to testnet/mainnet for validation. +This bridges the gap between isolated local tests and deploying to testnet/mainnet for validation. #### Quick start @@ -353,17 +355,25 @@ This means you typically do not need to change imports in your test code when sw #### Limitations and considerations -- Network performance: tests may run slower than local emulator tests due to network calls +- External dependency: requires connectivity to an access node; observe availability and rate limits - Point-in-time snapshot: forked state reflects the time of query (or the specified `--fork-height`), not a live stream - Read-only network: mutations in your tests are local and do not affect the real network - Spork boundaries: access nodes only retain historical data for the current spork; pinning via `--fork-height` cannot reach beyond that boundary. Learn more about the Flow spork process in the Network Upgrade (Spork) docs. +- External oracles/off-chain systems: forked tests cannot fetch live data from external services or other chains; provide mocks or a local test harness See: [Network Upgrade (Spork) Process](../../../protocol/node-ops/node-operation/network-upgrade.md) +See also: + +- Strategy: [Testing Strategy on Flow](./testing-strategy.md) +- Flags: [Fork Testing Flags](../../tools/flow-cli/tests.md#fork-testing-flags) +- Emulator (fork mode): [Flow Emulator](../../tools/emulator/index.md) + #### Best practices -1. Use fork testing primarily for integration tests; keep unit tests on the emulator for speed -2. Keep forked tests separate in CI and run them selectively +1. Use fork testing primarily for integration tests; keep unit tests on the emulator for determinism and isolation +2. Keep forked tests separate in CI. On PRs, run them pinned (full suite if practical; otherwise a small smoke set) +3. For reproducibility, pin with `--fork-height` where it matters. For best results, maintain a per‑spork stable pin and also run a "latest" freshness job 3. Prefer testnet before mainnet to catch network-specific issues with fewer risks 4. Document dependencies on specific mainnet/testnet contracts and addresses 5. Consider real data requirements—fork testing shines when reading existing on-chain state diff --git a/docs/build/tools/emulator/index.md b/docs/build/tools/emulator/index.md index d22893cc34..1fe624d3ab 100644 --- a/docs/build/tools/emulator/index.md +++ b/docs/build/tools/emulator/index.md @@ -64,6 +64,7 @@ For all available options, see the [CLI commands overview](../flow-cli/index.md) - **Code Coverage**: Add `--coverage-reporting` flag and visit `http://localhost:8080/emulator/codeCoverage` - **Debugging**: Use `#debugger()` pragma in Cadence code for breakpoints +- **Fork mode note**: When using `flow emulator --fork`, only Flow chain state is available. External oracles/APIs and cross-chain reads are not live; mock these or run local stub services for E2E. ## Snapshots diff --git a/docs/build/tools/flow-cli/tests.md b/docs/build/tools/flow-cli/tests.md index 3e1b9f7ea3..b94a6998e7 100644 --- a/docs/build/tools/flow-cli/tests.md +++ b/docs/build/tools/flow-cli/tests.md @@ -106,15 +106,15 @@ To learn more about writing tests in Cadence, visit the [Cadence Testing Framewo --- -### Running Specific Tests +### Running Specific Tests and Files -If you wish to run a specific test script rather than all tests, you can provide the path to the test file: +Run specific test scripts or directories by providing their paths: ```shell -flow test path/to/your/test_script_test.cdc +flow test path/to/your/test_script_test.cdc path/to/another_test.cdc tests/subsuite/ ``` -This will execute only the tests contained in the specified file. +This executes only the tests contained in the specified files and directories. --- From a13d8ade9747d35c4e33e3d1d67db3722d643303 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 07:24:01 -0700 Subject: [PATCH 05/23] tidy --- docs/build/cadence/smart-contracts/testing.md | 5 +---- docs/protocol/flow-networks/index.md | 3 --- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index e02baa5905..b8689cdcaa 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -341,9 +341,6 @@ flow test tests/my_marketplace_test.cdc --fork mainnet # Pin to a specific block height for historical state flow test --fork mainnet --fork-height 85432100 - -# Generate coverage while forking -flow test --fork --cover ``` #### How contract aliases are resolved @@ -389,7 +386,7 @@ Guide → Flags: [Fork Testing Flags](../../../build/tools/flow-cli/tests.md#for ```bash flow test --fork # Fork from mainnet (default when value omitted) flow test --fork testnet # Fork from testnet -flow test --fork --cover # With coverage report +# flow test --cover # With coverage report flow test --fork --fork-height NUM # Pin to block height ``` diff --git a/docs/protocol/flow-networks/index.md b/docs/protocol/flow-networks/index.md index dc41cf216a..8ade53bf55 100644 --- a/docs/protocol/flow-networks/index.md +++ b/docs/protocol/flow-networks/index.md @@ -27,9 +27,6 @@ For more information on how to access these networks, refer to the following gui - [Flow Testnet](./accessing-testnet.md) - [Flow Mainnet](./accessing-mainnet.md) - -You can use these public GRPC hosts directly with forked tests via `flow test --fork-host `. See the CLI reference: [Fork Testing Flags](../../build/tools/flow-cli/tests.md#fork-testing-flags). - ### Network From 7fecfd533d16561371b2a674ac1a092491ae502b Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 07:51:19 -0700 Subject: [PATCH 06/23] cleanup links --- .../cadence/fork-testing/index.md | 8 +++-- .../smart-contracts/testing-strategy.md | 34 +++++++++++------- docs/build/cadence/smart-contracts/testing.md | 35 ++++++++++++------- docs/build/tools/emulator/index.md | 26 ++++++++++---- 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index 3b3564fd82..d2ec915df2 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -493,9 +493,9 @@ You can also fork from testnet (`flow test --fork testnet`) or pin to a specific See also: -- High-Level Testing Strategy: [Testing Strategy on Flow](../../../build/cadence/smart-contracts/testing-strategy.md) -- Emulator (fork mode for interactive E2E): [Flow Emulator](../../../build/tools/emulator/index.md) -- Networks and access nodes: [Flow Networks](../../../protocol/flow-networks/index.md) +- Strategy: [Testing Strategy on Flow] +- Emulator (fork mode for interactive E2E): [Flow Emulator] +- Networks and access nodes: [Flow Networks] ::::info External oracles and off-chain systems @@ -568,5 +568,7 @@ Fork testing bridges the gap between local unit tests and testnet deployments, e [Fork Testing Flags]: ../../../build/tools/flow-cli/tests.md#fork-testing-flags [Cadence Testing Framework]: https://cadence-lang.org/docs/testing-framework [Flow Networks]: ../../../protocol/flow-networks/index.md +[Testing Strategy on Flow]: ../../../build/cadence/smart-contracts/testing-strategy.md +[Flow Emulator]: ../../../build/tools/emulator/index.md diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index 8e847fe2a1..aa75a5009a 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -114,15 +114,25 @@ flow emulator --fork mainnet --fork-height ## Related docs -- Guide → Running tests: [Running Cadence Tests](../../tools/flow-cli/tests.md) -- Guide → Background: [Testing Smart Contracts](./testing.md) -- Tutorial → Step-by-step: [Fork Testing with Cadence](../../../blockchain-development-tutorials/cadence/fork-testing/index.md) -- Tool → Emulator (including fork mode): [Flow Emulator](../../tools/emulator/index.md) -- Flags → `flow test --fork`: [Fork Testing Flags](../../tools/flow-cli/tests.md#fork-testing-flags) -- Networks → Public access nodes: [Flow Networks](../../../protocol/flow-networks/index.md) -- Upgrades → Spork boundaries: [Network Upgrade (Spork) Process](../../../protocol/node-ops/node-operation/network-upgrade.md) -- Config → Network and hosts: [Flow CLI Configuration (flow.json)](../../tools/flow-cli/flow.json/initialize-configuration.md) -- Imports → Resolving aliases: [Dependency Manager](../../tools/flow-cli/dependency-manager.md) -- Language → Assertions & helpers: [Cadence Testing Framework](https://cadence-lang.org/docs/testing-framework) - - +- Guide → Running tests: [Running Cadence Tests] +- Guide → Background: [Testing Smart Contracts] +- Tutorial → Step-by-step: [Fork Testing with Cadence] +- Tool → Emulator (including fork mode): [Flow Emulator] +- Flags → `flow test --fork`: [Fork Testing Flags] +- Networks → Public access nodes: [Flow Networks] +- Upgrades → Spork boundaries: [Network Upgrade (Spork) Process] +- Config → Network and hosts: [Flow CLI Configuration (flow.json)] +- Imports → Resolving aliases: [Dependency Manager] +- Language → Assertions & helpers: [Cadence Testing Framework] + + +[Running Cadence Tests]: ../../tools/flow-cli/tests.md +[Testing Smart Contracts]: ./testing.md +[Fork Testing with Cadence]: ../../../blockchain-development-tutorials/cadence/fork-testing/index.md +[Flow Emulator]: ../../tools/emulator/index.md +[Fork Testing Flags]: ../../tools/flow-cli/tests.md#fork-testing-flags +[Flow Networks]: ../../../protocol/flow-networks/index.md +[Network Upgrade (Spork) Process]: ../../../protocol/node-ops/node-operation/network-upgrade.md +[Flow CLI Configuration (flow.json)]: ../../tools/flow-cli/flow.json/initialize-configuration.md +[Dependency Manager]: ../../tools/flow-cli/dependency-manager.md +[Cadence Testing Framework]: https://cadence-lang.org/docs/testing-framework diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index b8689cdcaa..6692eab32a 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -27,17 +27,17 @@ keywords: Testing is an essential part of smart contract development to ensure the correctness and reliability of your code. The Cadence Testing Framework provides a convenient way to write tests for your contracts, scripts and transactions which allows you to verify the functionality and correctness of your smart contracts. -> For a layered approach to when and why to use emulator, forked integration, and testnet, see the strategy guide: [Testing Strategy on Flow](./testing-strategy.md). +> For a layered approach to when and why to use emulator, forked integration, and testnet, see the strategy guide: [Testing Strategy on Flow]. ## Install Flow CLI -The [Flow CLI](../../../build/tools/flow-cli/index.md) is the primary tool for developing, testing, and deploying smart contracts to the Flow network. +The [Flow CLI] is the primary tool for developing, testing, and deploying smart contracts to the Flow network. -If you haven't installed the Flow CLI yet and have [homebrew](https://brew.sh/) installed, simply run `brew install flow-cli`. Alternatively, refer to the Flow CLI [installation instructions](../../../build/tools/flow-cli/install.md). +If you haven't installed the Flow CLI yet and have [homebrew](https://brew.sh/) installed, simply run `brew install flow-cli`. Alternatively, refer to the Flow CLI [installation instructions]. ## Create a new project -In your preferred code editor, create a new directory for your project and navigate to it in the terminal. Then initialize a new Flow project by running the command `flow init`. This will create a `flow.json` config file that contains the [project's configuration](../../../build/tools/flow-cli/flow.json/configuration.md). +In your preferred code editor, create a new directory for your project and navigate to it in the terminal. Then initialize a new Flow project by running the command `flow init`. This will create a `flow.json` config file that contains the [project's configuration]. ```bash mkdir test-cadence @@ -220,7 +220,7 @@ By leveraging these advanced testing techniques, you can write more robust and r This is a basic example, and there are many more advanced features and techniques you can explore when working with the Cadence Testing Framework. -For more in-depth tutorials and documentation, refer to the official [Cadence language documentation](https://cadence-lang.org/) and the [Flow CLI documentation](../../../build/tools/flow-cli/index.md). +For more in-depth tutorials and documentation, refer to the official [Cadence language documentation](https://cadence-lang.org/) and the [Flow CLI documentation]. ## Testing Requirements @@ -242,7 +242,7 @@ In all three cases, the test code will need to deploy the contracts, configure a ### Cadence tests Cadence comes with built-in support for code coverage, as well as a native testing framework which allows developers to write their tests using Cadence. -This framework is bundled with the [Flow CLI](../../../build/tools/flow-cli/index.md) tool, which includes a dedicated command for running tests (`flow test`). +This framework is bundled with the [Flow CLI] tool, which includes a dedicated command for running tests (`flow test`). You can find examples of Cadence tests in the following projects: [hybrid-custody](https://github.com/onflow/hybrid-custody/tree/main/test), [flow-nft](https://github.com/onflow/flow-nft/tree/master/tests), [flow-ft](https://github.com/onflow/flow-ft/tree/master/tests). Visit the [documentation](https://cadence-lang.org/docs/testing-framework) to view all the available features. @@ -358,13 +358,13 @@ This means you typically do not need to change imports in your test code when sw - Spork boundaries: access nodes only retain historical data for the current spork; pinning via `--fork-height` cannot reach beyond that boundary. Learn more about the Flow spork process in the Network Upgrade (Spork) docs. - External oracles/off-chain systems: forked tests cannot fetch live data from external services or other chains; provide mocks or a local test harness -See: [Network Upgrade (Spork) Process](../../../protocol/node-ops/node-operation/network-upgrade.md) +See: [Network Upgrade (Spork) Process] See also: -- Strategy: [Testing Strategy on Flow](./testing-strategy.md) -- Flags: [Fork Testing Flags](../../tools/flow-cli/tests.md#fork-testing-flags) -- Emulator (fork mode): [Flow Emulator](../../tools/emulator/index.md) +- Strategy: [Testing Strategy on Flow] +- Flags: [Fork Testing Flags] +- Emulator (fork mode): [Flow Emulator] #### Best practices @@ -379,9 +379,9 @@ See also: See the flag reference for available options and details. -Guide → Tutorial: [Fork Testing with Cadence (Step-by-Step)](../../../blockchain-development-tutorials/cadence/fork-testing/index.md) +Guide → Tutorial: [Fork Testing with Cadence (Step-by-Step)] -Guide → Flags: [Fork Testing Flags](../../../build/tools/flow-cli/tests.md#fork-testing-flags) +Guide → Flags: [Fork Testing Flags] ```bash flow test --fork # Fork from mainnet (default when value omitted) @@ -424,3 +424,14 @@ Get familiar with the [Cadence anti-patterns](https://cadence-lang.org/docs/anti - [hybrid-custody](https://github.com/onflow/hybrid-custody/tree/main/test), - [flow-nft](https://github.com/onflow/flow-nft/tree/master/tests), - [flow-ft](https://github.com/onflow/flow-ft/tree/master/tests). + + +[Testing Strategy on Flow]: ./testing-strategy.md +[Flow CLI]: ../../../build/tools/flow-cli/index.md +[installation instructions]: ../../../build/tools/flow-cli/install.md +[project's configuration]: ../../../build/tools/flow-cli/flow.json/configuration.md +[Flow CLI documentation]: ../../../build/tools/flow-cli/index.md +[Network Upgrade (Spork) Process]: ../../../protocol/node-ops/node-operation/network-upgrade.md +[Fork Testing Flags]: ../../tools/flow-cli/tests.md#fork-testing-flags +[Flow Emulator]: ../../tools/emulator/index.md +[Fork Testing with Cadence (Step-by-Step)]: ../../../blockchain-development-tutorials/cadence/fork-testing/index.md \ No newline at end of file diff --git a/docs/build/tools/emulator/index.md b/docs/build/tools/emulator/index.md index b444236e60..59ae3b1965 100644 --- a/docs/build/tools/emulator/index.md +++ b/docs/build/tools/emulator/index.md @@ -8,7 +8,7 @@ The Flow Emulator is a lightweight tool that emulates the behavior of the real F ## Installation -The emulator is included with the [Flow CLI](../flow-cli/index.md). Follow the [installation guide](../flow-cli/install.md) to get started. +The emulator is included with the [Flow CLI]. Follow the [installation guide] to get started. ## Quick Start @@ -18,10 +18,10 @@ First, create a `flow.json` configuration file: flow init --config-only ``` -Then start the Flow Emulator: +Then start the Flow Emulator in fork mode (defaults to mainnet when value omitted): ```bash -flow emulator +flow emulator --fork ``` You'll see output similar to: @@ -41,7 +41,7 @@ This starts a local Flow network with: ## Available Commands -- `snapshot`: Create/Load/List emulator snapshots. See: [Create Emulator Snapshot](../flow-cli/deployment/emulator-snapshot.md) +- `snapshot`: Create/Load/List emulator snapshots. See: [Create Emulator Snapshot] ## Key Flags @@ -63,6 +63,7 @@ This starts a local Flow network with: - `--state-hash `: Load state from checkpoint state hash - **Forking** + - `--fork `: Start the emulator in fork mode using a network from `flow.json`. If provided without a value, defaults to `mainnet`. - `--fork-host `: Access node to query when forking Mainnet/Testnet - `--fork-height `: Starting block height when forking @@ -116,6 +117,12 @@ flow emulator --block-time 1s # Persist state on disk flow emulator --persist --dbpath ./flowdb +# Fork from Mainnet using flow.json +flow emulator --fork + +# Fork from Testnet using flow.json and pin to a height +flow emulator --fork testnet --fork-height 12345678 + # Fork from Testnet at a specific height flow emulator --fork-host access.devnet.nodes.onflow.org:9000 --fork-height 12345678 @@ -172,8 +179,13 @@ To list all the existing snapshots we previously created and can load to run: flow emulator list ``` -To learn more about using the Emulator, have a look at the [README of the repository](https://github.com/onflow/flow-emulator). - ## Additional Resources -For advanced configuration options, see the [Flow Emulator repository](https://github.com/onflow/flow-emulator/). +To learn more about using the Emulator, please have a look at the [public GitHub repository]. + + + +[Flow CLI]: ../flow-cli/index.md +[installation guide]: ../flow-cli/install.md +[Create Emulator Snapshot]: ../flow-cli/utils/snapshot-save.md +[public GitHub repository]: https://github.com/onflow/flow-emulator \ No newline at end of file From a7ece89a279648550c19c7476da70df592456de5 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 07:54:27 -0700 Subject: [PATCH 07/23] Regenerate keywords for testing docs to reflect comprehensive fork testing content --- .../cadence/fork-testing/index.md | 16 ++++++++++++- .../smart-contracts/testing-strategy.md | 19 +++++++++++++-- docs/build/cadence/smart-contracts/testing.md | 14 +++++++++++ docs/build/tools/emulator/index.md | 23 +++++++++++++++++++ docs/build/tools/flow-cli/tests.md | 23 +++++++++++++++++++ 5 files changed, 92 insertions(+), 3 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index d2ec915df2..3f9374193c 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -5,7 +5,7 @@ title: Fork Testing with Cadence description: Run your Cadence test suite against a forked mainnet or testnet using flow test --fork. Test against real contracts and production data without deploying to live networks. keywords: - fork testing - - flow test + - flow test --fork - cadence tests - mainnet fork - testnet fork @@ -13,6 +13,20 @@ keywords: - Flow CLI - account impersonation - production testing + - real contracts + - on-chain state + - block height + - fork-height + - historical debugging + - reproducible tests + - test deployment + - FlowToken + - FungibleToken + - test scripts + - test transactions + - local testing + - safe testing + - forked runtime --- # Fork Testing with Cadence diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index aa75a5009a..bd57abbfaa 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -5,13 +5,28 @@ sidebar_position: 3 description: A layered testing strategy for Flow—emulator unit/property tests, forked integration, emulator fork sandbox, testnet canaries, and post-deploy monitoring. Guidance for reproducibility, CI selection, and triage. keywords: - testing strategy + - unit testing + - integration testing - fork testing + - flow test --fork + - flow emulator --fork - emulator - - CI + - testnet + - CI pipeline + - continuous integration - reproducibility - - pins + - fork-height + - block height pinning + - test selection + - smoke tests + - E2E testing + - account impersonation + - test triage + - golden files + - test automation - Flow CLI - Cadence tests + - spork boundaries --- # Testing Strategy on Flow diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index 6692eab32a..d6686449a5 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -21,6 +21,20 @@ keywords: - automated testing - contract verification - testing best practices + - fork testing + - flow test --fork + - emulator testing + - mainnet fork + - testnet fork + - fork-height + - account impersonation + - reproducible tests + - test deployment + - testing aliases + - spork boundaries + - Go tests + - external oracles + - off-chain mocking --- # Testing Smart Contracts diff --git a/docs/build/tools/emulator/index.md b/docs/build/tools/emulator/index.md index 59ae3b1965..c15bf556ec 100644 --- a/docs/build/tools/emulator/index.md +++ b/docs/build/tools/emulator/index.md @@ -2,6 +2,29 @@ title: Flow Emulator description: Local Flow network for development and testing sidebar_position: 3 +keywords: + - Flow Emulator + - local development + - testing + - flow emulator --fork + - fork mode + - emulator flags + - mainnet fork + - testnet fork + - fork-height + - fork-host + - gRPC server + - REST API + - snapshots + - persistent storage + - block time + - code coverage + - debugging + - service account + - Flow CLI + - local blockchain + - E2E testing + - off-chain mocking --- The Flow Emulator is a lightweight tool that emulates the behavior of the real Flow network for local development and testing. diff --git a/docs/build/tools/flow-cli/tests.md b/docs/build/tools/flow-cli/tests.md index b94a6998e7..2b55d5bacb 100644 --- a/docs/build/tools/flow-cli/tests.md +++ b/docs/build/tools/flow-cli/tests.md @@ -3,6 +3,29 @@ title: Running Cadence Tests sidebar_label: Running Cadence Tests description: How to run Cadence tests from the CLI sidebar_position: 11 +keywords: + - flow test + - Cadence tests + - Flow CLI + - test command + - test flags + - code coverage + - fork testing + - flow test --fork + - fork-height + - fork-host + - mainnet fork + - testnet fork + - test discovery + - test aliases + - testing configuration + - test selection + - test by name + - random testing + - coverage reporting + - test automation + - integration testing + - spork boundaries --- The Flow CLI provides a straightforward command to execute Cadence tests, enabling developers to validate their scripts and smart contracts effectively. From f845c665576728bd3c6835ffae5de8cbbfd60e34 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 07:55:03 -0700 Subject: [PATCH 08/23] Revert incorrect --rpc-host change in EVM gateway setup (unrelated to emulator fork flags) --- docs/protocol/node-ops/evm-gateway/evm-gateway-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/protocol/node-ops/evm-gateway/evm-gateway-setup.md b/docs/protocol/node-ops/evm-gateway/evm-gateway-setup.md index 8732ff6234..c8da6704b9 100644 --- a/docs/protocol/node-ops/evm-gateway/evm-gateway-setup.md +++ b/docs/protocol/node-ops/evm-gateway/evm-gateway-setup.md @@ -233,7 +233,7 @@ ExecStart=/usr/bin/evm-gateway \ --coa-address=$COA_ADDRESS \ --coa-key=$COA_KEY \ --rate-limit=9999999 \ ---fork-host=0.0.0.0 \ +--rpc-host=0.0.0.0 \ --gas-price=$GAS_PRICE \ --tx-state-validation=local-index Restart=always From d0ce7e09b28398f997974ad5a4d7b1158c252bb0 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 08:07:58 -0700 Subject: [PATCH 09/23] remove jargon --- .../smart-contracts/testing-strategy.md | 44 +++++++++---------- docs/build/cadence/smart-contracts/testing.md | 2 +- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index bd57abbfaa..6d71b3e592 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -2,7 +2,7 @@ title: Testing Strategy on Flow sidebar_label: Testing Strategy sidebar_position: 3 -description: A layered testing strategy for Flow—emulator unit/property tests, forked integration, emulator fork sandbox, testnet canaries, and post-deploy monitoring. Guidance for reproducibility, CI selection, and triage. +description: A layered testing strategy for Flow—unit tests, forked integration, and a forked emulator sandbox. Guidance for reproducibility and simple CI setup. keywords: - testing strategy - unit testing @@ -21,7 +21,7 @@ keywords: - smoke tests - E2E testing - account impersonation - - test triage + - test troubleshooting - golden files - test automation - Flow CLI @@ -35,26 +35,29 @@ A single, pragmatic strategy for testing on Flow. Use layers that are determinis ## At a glance -- **Unit & Property (emulator, no fork)**: Hermetic correctness and invariants -- **Integration (automated, `flow test --fork`)**: Real contracts and data; mutations stay local +- **Unit & Property — Test Framework**: Hermetic correctness and invariants +- **Integration — `flow test --fork`**: Real contracts and data; mutations stay local - **Local integration sandbox (interactive, `flow emulator --fork`)**: Drive apps/E2E against production-like state - **Staging (testnet)**: Final plumbing and config checks - **Post-deploy (read-only)**: Invariant dashboards and alerts ## Layers -### Unit & Property (Emulator, no fork) +### Unit & Property — Test Framework +- Use `flow test` - **Use when**: Validating Cadence logic, invariants, access control, error paths, footprint - **Why**: Fully deterministic and isolated; highest-regression signal - **Run**: Every commit/PR; wide parallelism -- **Notes**: Favor property/invariant checks and fuzzing; zero external dependencies + - **Notes**: Write clear success/failure tests, add simple “this should always hold” rules when helpful, and avoid external services -### Integration (Automated) — `flow test --fork` +See also: [Running Cadence Tests]. + +### Integration — `flow test --fork` - **Use when**: Interacting with real on-chain contracts/data (FT/NFT standards, AMMs, wallets, oracles, bridges), upgrade checks, historical repro - **Why**: Real addresses, capability paths, and resource schemas; catches drift early - - **Run**: PRs may run the full forked suite (pinned) or a small smoke subset; broader matrix nightly/on merge +- **Run**: On PRs, run the full forked suite if practical (pinned), or a small quick set; run more cases nightly or on main - **Notes**: - Pin with `--fork-height` where reproducibility matters - Prefer local deployment + impersonation over real mainnet accounts @@ -62,6 +65,8 @@ A single, pragmatic strategy for testing on Flow. Use layers that are determinis - Be mindful of access-node availability and rate limits - External oracles/protocols: forked tests do not call off-chain services or other chains; mock these or run a local stub +See also: [Fork Testing with Cadence], [Fork Testing Flags]. + ### Local Integration Sandbox (Interactive) — `flow emulator --fork` - **Use when**: Driving dapps, wallets, bots, indexers, or exploratory debugging outside the test framework @@ -69,6 +74,8 @@ A single, pragmatic strategy for testing on Flow. Use layers that are determinis - **Run**: Dev machines and focused E2E CI jobs - **Notes**: Pin height; run on dedicated ports; impersonation is built-in; mutations are local; off-chain/oracle calls are not live—mock or run local stubs +See also: [Flow Emulator]. + ### Staging — Testnet - **Use when**: Final network plumbing and configuration checks before release @@ -76,6 +83,8 @@ A single, pragmatic strategy for testing on Flow. Use layers that are determinis - **Run**: Pre-release and on infra changes - **Notes**: Keep canaries minimal and time-boxed; protocol/partner support may be limited on testnet (not all third-party contracts are deployed or up to date) +See also: [Flow Networks]. + ### Post-deploy Monitoring (read-only) - **Use when**: After releases to confirm invariants and event rates @@ -91,8 +100,8 @@ A single, pragmatic strategy for testing on Flow. Use layers that are determinis ## CI tips -- PRs: Run emulator unit/property and forked integration (pinned). Full suite is fine if practical; otherwise a small smoke set. -- Nightly/Main: Add a latest pin job and a broader fork matrix when needed. +- PRs: Run emulator unit/property and forked integration (pinned). Full suite is fine if practical; otherwise a small quick set. +- Nightly/Main: Add a latest pin job and expand fork coverage as needed. - E2E (optional): Use `flow emulator --fork` at a stable pin and run your browser tests. ## Test selection and tagging @@ -100,27 +109,16 @@ A single, pragmatic strategy for testing on Flow. Use layers that are determinis - **Optional naming helpers**: Use simple suffixes in test names like `_fork`, `_smoke`, `_e2e` if helpful - Run the tests you care about by passing files/directories: `flow test FILE1 FILE2 DIR1 ...` (most common) - Optionally, use `--name ` to match test functions when it’s convenient -- **Defaults**: PRs can run the full fork suite (pinned) or a small smoke set; nightly runs the full matrix (+ optional E2E) +- **Defaults**: PRs can run the full fork suite (pinned) or a small quick set; nightly runs broader coverage (+ optional E2E) -## Triage tips +## Troubleshooting tips - Re-run at the same `--fork-height`, then at latest - Compare contract addresses/aliases in `flow.json` - Diff event/resource shapes against your stored samples - Check access-node health and CI parallelism/sharding -## Handy commands - -```bash -# Unit/property (emulator) -flow test - -# Forked integration (pinned) -flow test --fork mainnet --fork-height -# Local sandbox (interactive) -flow emulator --fork mainnet --fork-height -``` ## Do / Don’t diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index d6686449a5..d3b1b575c5 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -383,7 +383,7 @@ See also: #### Best practices 1. Use fork testing primarily for integration tests; keep unit tests on the emulator for determinism and isolation -2. Keep forked tests separate in CI. On PRs, run them pinned (full suite if practical; otherwise a small smoke set) +2. Keep forked tests separate in CI. On PRs, run them pinned (full suite if practical; otherwise a small quick set) 3. For reproducibility, pin with `--fork-height` where it matters. For best results, maintain a per‑spork stable pin and also run a "latest" freshness job 3. Prefer testnet before mainnet to catch network-specific issues with fewer risks 4. Document dependencies on specific mainnet/testnet contracts and addresses From 3f95826b8c6b1df5e94ee09a9429918c1354e236 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 08:33:14 -0700 Subject: [PATCH 10/23] reorg --- .../cadence/fork-testing/index.md | 2 +- .../smart-contracts/testing-strategy.md | 11 +- docs/build/cadence/smart-contracts/testing.md | 164 +----------------- 3 files changed, 15 insertions(+), 162 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index 3f9374193c..99e3d09857 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -577,7 +577,7 @@ Fork testing bridges the gap between local unit tests and testnet deployments, e [Flow CLI]: ../../../build/tools/flow-cli/index.md [homebrew]: https://brew.sh [installation guide]: ../../../build/tools/flow-cli/install.md -[Testing Smart Contracts]: ../../../build/cadence/smart-contracts/testing.md +[Testing Smart Contracts]: ../../../build/cadence/smart-contracts/testing-strategy.md [Dependency Manager]: ../../../build/tools/flow-cli/dependency-manager.md [Fork Testing Flags]: ../../../build/tools/flow-cli/tests.md#fork-testing-flags [Cadence Testing Framework]: https://cadence-lang.org/docs/testing-framework diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index 6d71b3e592..051ff35d76 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -1,6 +1,6 @@ --- -title: Testing Strategy on Flow -sidebar_label: Testing Strategy +title: Testing Smart Contracts +sidebar_label: Testing Smart Contracts sidebar_position: 3 description: A layered testing strategy for Flow—unit tests, forked integration, and a forked emulator sandbox. Guidance for reproducibility and simple CI setup. keywords: @@ -29,10 +29,9 @@ keywords: - spork boundaries --- -# Testing Strategy on Flow +# Testing Smart Contracts A single, pragmatic strategy for testing on Flow. Use layers that are deterministic and isolated by default, add realism with forks when needed, and keep a minimal set of live network checks before release. - ## At a glance - **Unit & Property — Test Framework**: Hermetic correctness and invariants @@ -128,7 +127,7 @@ See also: [Flow Networks]. ## Related docs - Guide → Running tests: [Running Cadence Tests] -- Guide → Background: [Testing Smart Contracts] +- Guide → How-to: [Cadence Testing Framework] - Tutorial → Step-by-step: [Fork Testing with Cadence] - Tool → Emulator (including fork mode): [Flow Emulator] - Flags → `flow test --fork`: [Fork Testing Flags] @@ -140,7 +139,7 @@ See also: [Flow Networks]. [Running Cadence Tests]: ../../tools/flow-cli/tests.md -[Testing Smart Contracts]: ./testing.md +[Cadence Testing Framework]: ./testing.md [Fork Testing with Cadence]: ../../../blockchain-development-tutorials/cadence/fork-testing/index.md [Flow Emulator]: ../../tools/emulator/index.md [Fork Testing Flags]: ../../tools/flow-cli/tests.md#fork-testing-flags diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index d3b1b575c5..2d02b45f03 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -1,47 +1,26 @@ --- -title: Testing Smart Contracts -sidebar_label: Testing Smart Contracts -description: Learn comprehensive testing strategies for Flow smart contracts. Master unit testing, integration testing, and code coverage using the Cadence Testing Framework and Flow CLI. +title: Cadence Testing Framework +sidebar_label: Cadence Testing Framework +description: Learn how to write and run tests for Cadence contracts, scripts, and transactions using the Cadence Testing Framework and Flow CLI. sidebar_position: 4 sidebar_custom_props: icon: 📝 keywords: - - smart contract testing - Cadence testing - - test coverage - unit tests - - integration tests - - Flow CLI - - test automation - - testing framework - - test suites - code coverage + - Flow CLI - test assertions - test helpers - - automated testing - - contract verification - - testing best practices - - fork testing - - flow test --fork - - emulator testing - - mainnet fork - - testnet fork - - fork-height - - account impersonation - - reproducible tests - - test deployment - - testing aliases - - spork boundaries - - Go tests - - external oracles - - off-chain mocking --- # Testing Smart Contracts Testing is an essential part of smart contract development to ensure the correctness and reliability of your code. The Cadence Testing Framework provides a convenient way to write tests for your contracts, scripts and transactions which allows you to verify the functionality and correctness of your smart contracts. -> For a layered approach to when and why to use emulator, forked integration, and testnet, see the strategy guide: [Testing Strategy on Flow]. + +Looking for high‑level guidance on when to use emulator, forks, or testnet? See Testing Smart Contracts. + ## Install Flow CLI @@ -275,134 +254,9 @@ There is also a [repository](https://github.com/m-Peter/flow-code-coverage#readm The Cadence testing framework utilizes the emulator under the hood. -### Fork Testing - -Fork testing lets you run your Cadence test files (`*_test.cdc`) against a snapshot of a live Flow network (mainnet or testnet). This enables realistic integration tests that read real contract code and on-chain state while keeping all mutations local to your test run. - - -This section covers `flow test --fork` (running tests against a forked network), which is different from `flow emulator --fork` (starting the emulator in fork mode for manual interaction). - - -#### What is fork testing? - -When you run tests with the `--fork` flag, the test runner: - -- Connects to a Flow access node (public or custom) -- Fetches account state, contract code, and other data on demand -- Executes your tests as if they are running against the live network state -- Keeps all state changes local to your test process (the real network is never mutated) - -This bridges the gap between isolated local tests and deploying to testnet/mainnet for validation. - -#### Quick start - -Example: Read from the real FlowToken contract on mainnet. - -```cadence flow_token_test.cdc -import Test -import "FlowToken" // Resolves to mainnet alias when running with --fork - -access(all) fun testFlowTokenSupplyIsPositive() { - let supply = FlowToken.totalSupply - Test.assert(supply > 0.0, message: "FlowToken supply should be positive") -} -``` - -Ensure your `flow.json` defines the mainnet alias for `FlowToken`: - -```json -{ - "contracts": { - "FlowToken": { - "source": "./cadence/contracts/FlowToken.cdc", - "aliases": { - "mainnet": "0x1654653399040a61" - } - } - }, - "networks": { - "mainnet": { - "host": "access.mainnet.nodes.onflow.org:9000" - } - } -} -``` +### Fork testing (overview) -Run the test against a fork of mainnet: - -```bash -flow test --fork -``` - -To target testnet instead: - -```bash -flow test --fork testnet -``` - -#### Common use cases - -- Integration testing with real contracts (NFT marketplaces, DEXs, core contracts) -- Pre-deployment validation against production data -- Upgrade testing with production state -- Historical debugging with a specific block height - -Examples: - -```bash -# Run a single test file against mainnet -flow test tests/my_marketplace_test.cdc --fork mainnet - -# Pin to a specific block height for historical state -flow test --fork mainnet --fork-height 85432100 -``` - -#### How contract aliases are resolved - -- Normal mode (no `--fork`): your imports use the `testing` aliases from `flow.json` (for emulator deployments) -- Fork mode: imports automatically use the aliases for the selected network (e.g. `mainnet` or `testnet`) defined in `flow.json` - -This means you typically do not need to change imports in your test code when switching between local and forked runs—configure aliases once and select the mode via flags. - -#### Limitations and considerations - -- External dependency: requires connectivity to an access node; observe availability and rate limits -- Point-in-time snapshot: forked state reflects the time of query (or the specified `--fork-height`), not a live stream -- Read-only network: mutations in your tests are local and do not affect the real network -- Spork boundaries: access nodes only retain historical data for the current spork; pinning via `--fork-height` cannot reach beyond that boundary. Learn more about the Flow spork process in the Network Upgrade (Spork) docs. -- External oracles/off-chain systems: forked tests cannot fetch live data from external services or other chains; provide mocks or a local test harness - -See: [Network Upgrade (Spork) Process] - -See also: - -- Strategy: [Testing Strategy on Flow] -- Flags: [Fork Testing Flags] -- Emulator (fork mode): [Flow Emulator] - -#### Best practices - -1. Use fork testing primarily for integration tests; keep unit tests on the emulator for determinism and isolation -2. Keep forked tests separate in CI. On PRs, run them pinned (full suite if practical; otherwise a small quick set) -3. For reproducibility, pin with `--fork-height` where it matters. For best results, maintain a per‑spork stable pin and also run a "latest" freshness job -3. Prefer testnet before mainnet to catch network-specific issues with fewer risks -4. Document dependencies on specific mainnet/testnet contracts and addresses -5. Consider real data requirements—fork testing shines when reading existing on-chain state - -#### Commands reference - -See the flag reference for available options and details. - -Guide → Tutorial: [Fork Testing with Cadence (Step-by-Step)] - -Guide → Flags: [Fork Testing Flags] - -```bash -flow test --fork # Fork from mainnet (default when value omitted) -flow test --fork testnet # Fork from testnet -# flow test --cover # With coverage report -flow test --fork --fork-height NUM # Pin to block height -``` +For running tests against a fork of mainnet/testnet, see the dedicated tutorial: [Fork Testing with Cadence (Step-by-Step)]. For available flags, see [Fork Testing Flags]. To interactively explore a forked state outside the test framework, see [Flow Emulator]. For when to use forks vs emulator, see [Testing Strategy on Flow]. ### Go Tests From f61a20cc24273a7c3bddf5d323aadf67035f8fb0 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 08:40:07 -0700 Subject: [PATCH 11/23] fix broken link --- docs/build/tools/flow-cli/tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build/tools/flow-cli/tests.md b/docs/build/tools/flow-cli/tests.md index 2b55d5bacb..a476c269d6 100644 --- a/docs/build/tools/flow-cli/tests.md +++ b/docs/build/tools/flow-cli/tests.md @@ -253,7 +253,7 @@ To dive deeper into testing the functionality of your Cadence scripts and contra ### Fork Testing Flags -Run tests against forked mainnet or testnet state. For a step-by-step tutorial, see: [Fork Testing with Cadence](../../../blockchain-development-tutorials/cadence/fork-testing/index.md). For background and best practices, see the guide: [Fork Testing](../../cadence/smart-contracts/testing.md#fork-testing). +Run tests against forked mainnet or testnet state. For a step-by-step tutorial, see: [Fork Testing with Cadence](../../../blockchain-development-tutorials/cadence/fork-testing/index.md). For background and best practices, see the guide: [Testing Strategy on Flow](../../cadence/smart-contracts/testing-strategy.md). #### --fork From 2b2e7bca67b61f2427fb3e656b5d799f87d21eb2 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 08:44:41 -0700 Subject: [PATCH 12/23] cleanup --- .../smart-contracts/testing-strategy.md | 5 ---- docs/build/cadence/smart-contracts/testing.md | 26 ------------------- 2 files changed, 31 deletions(-) diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index 051ff35d76..f1486d7bcc 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -131,11 +131,6 @@ See also: [Flow Networks]. - Tutorial → Step-by-step: [Fork Testing with Cadence] - Tool → Emulator (including fork mode): [Flow Emulator] - Flags → `flow test --fork`: [Fork Testing Flags] -- Networks → Public access nodes: [Flow Networks] -- Upgrades → Spork boundaries: [Network Upgrade (Spork) Process] -- Config → Network and hosts: [Flow CLI Configuration (flow.json)] -- Imports → Resolving aliases: [Dependency Manager] -- Language → Assertions & helpers: [Cadence Testing Framework] [Running Cadence Tests]: ../../tools/flow-cli/tests.md diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index 2d02b45f03..ece3fe4014 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -258,32 +258,6 @@ The Cadence testing framework utilizes the emulator under the hood. For running tests against a fork of mainnet/testnet, see the dedicated tutorial: [Fork Testing with Cadence (Step-by-Step)]. For available flags, see [Fork Testing Flags]. To interactively explore a forked state outside the test framework, see [Flow Emulator]. For when to use forks vs emulator, see [Testing Strategy on Flow]. -### Go Tests - -Tests in Go can be written using [flow-go-sdk](https://github.com/onflow/flow-go-sdk) and the go test command. - -You can find examples of Go tests in the following projects: [flow-core-contracts](https://github.com/onflow/flow-core-contracts/tree/master/lib/go/test), [flow-nft](https://github.com/onflow/flow-nft/tree/master/lib/go/test), [flow-ft](https://github.com/onflow/flow-ft/tree/master/lib/go/test). - - -These tests are tied to the emulator but can be refactored to run on testnet - - -## Testing Your Application - -### Automated Testing of Contract Code - -All contracts should include test coverage for _all contract functions_. Make sure you've accounted for success and failure cases appropriately. - -Tests should also be runnable in automated environments (CI). You can use the [Cadence testing utils](https://cadence-lang.org/docs/testing-framework) to create tests for your smart contract code. - -### Stress Testing Live Applications Before Mainnet - -Once you deployed your application to the testnet, you should record how your application handles non-trivial amounts of traffic to ensure there are no issues. - - -Get familiar with the [Cadence anti-patterns](https://cadence-lang.org/docs/anti-patterns) to avoid avoid problematic or unintended behavior. - - ## References - [Reference documentation for Cadence testing](https://cadence-lang.org/docs/testing-framework) From c22d3573ad3ff0cb6592e59b7cf8b7873ac479b6 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 09:14:05 -0700 Subject: [PATCH 13/23] fixup tutorial --- .../cadence/fork-testing/index.md | 110 ++++++++++-------- 1 file changed, 64 insertions(+), 46 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index 99e3d09857..ff0ea803a4 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -147,10 +147,10 @@ Your `flow.json` should now have the mainnet and testnet networks configured fro ## Test Reading Live State -Create the test directories: +The test directories are already created by `flow init`. If needed, create the scripts directory: ```zsh -mkdir -p tests cadence/scripts +mkdir -p cadence/scripts ``` First, create a script to read FlowToken supply. Create `cadence/scripts/GetFlowTokenSupply.cdc`: @@ -163,14 +163,14 @@ access(all) fun main(): UFix64 { } ``` -Now create the test file `tests/flow_token_test.cdc`: +Now create the test file `cadence/tests/flow_token_test.cdc`: -```cadence tests/flow_token_test.cdc +```cadence cadence/tests/flow_token_test.cdc import Test access(all) fun testFlowTokenSupplyIsPositive() { let scriptResult = Test.executeScript( - Test.readFile("cadence/scripts/GetFlowTokenSupply.cdc"), + Test.readFile("../scripts/GetFlowTokenSupply.cdc"), [] ) @@ -186,19 +186,20 @@ Notes: - The script imports `FlowToken` by name - the dependency manager handles address resolution - In fork mode, this automatically uses the mainnet FlowToken contract - Extract the return value with proper type casting and assert on it +- File paths in `Test.readFile()` are relative to the test file location (use `../scripts/` from `cadence/tests/`) #### Quick verify Run just this test file against a fork to confirm your setup works: ```zsh -flow test tests/flow_token_test.cdc --fork +flow test cadence/tests/flow_token_test.cdc --fork mainnet ``` Target testnet instead: ```zsh -flow test tests/flow_token_test.cdc --fork testnet +flow test cadence/tests/flow_token_test.cdc --fork testnet ``` You should see the test PASS. If not, verify your network host in `flow.json` and that dependencies are installed. @@ -207,15 +208,27 @@ You should see the test PASS. If not, verify your network host in `flow.json` an Now you'll create a contract that depends on FlowToken and test it against the forked mainnet state—no need to bootstrap tokens or set up test accounts. -### Create a Test Account +### Generate a Key Pair -Create a mainnet account for testing: +Generate a key pair that will be used for your test contract's mainnet alias: ```zsh -flow accounts create +flow keys generate ``` -When prompted, select `mainnet` as the network. This will generate a new account and save the private key to a `.pkey` file. Note the account address (e.g., `0xf8d6e0586b0a20c7`). +This will output a public/private key pair. Save the **private key** to a file: + +```zsh +echo "YOUR_PRIVATE_KEY_HERE" > mainnet-test.pkey +``` + +Note the **public key** - you'll need it to derive an account address. For fork testing, any valid Flow address format works. You can use this command to generate a test address from your key: + +```zsh +flow accounts derive-address mainnet-test.pkey +``` + +Or simply use a placeholder mainnet-format address like `f8d6e0586b0a20c7` for testing purposes. ### Create a Contract that Uses FlowToken @@ -248,32 +261,36 @@ access(all) contract TokenChecker { } ``` -### Configure Contract Deployment +### Configure Contract in flow.json + +Add the `TokenChecker` contract configuration to `flow.json`. The contract needs a **mainnet alias** so that imports can resolve properly during fork testing. -Add the deployment configuration to `flow.json`. The account you created in the previous step is already present under `accounts`; reference it here: +Update your `flow.json` to include the contract with aliases, using the address you generated in the previous step: ```json { "contracts": { "TokenChecker": { - "source": "cadence/contracts/TokenChecker.cdc" - } - }, - "deployments": { - "mainnet": { - "mainnet-account": ["TokenChecker"] + "source": "cadence/contracts/TokenChecker.cdc", + "aliases": { + "testing": "0000000000000008", + "mainnet": "" + } } }, "accounts": { - "mainnet-account": { - "address": "", - "key": "" + "mainnet-test": { + "address": "", + "key": { + "type": "file", + "location": "mainnet-test.pkey" + } } } } ``` -This configuration tells the test framework to deploy `TokenChecker` to your mainnet account when running fork tests. +The `Test.deployContract` function will automatically deploy your contract to the testing environment during test execution. ### Create Scripts for Testing @@ -299,16 +316,16 @@ access(all) fun main(addr: Address, min: UFix64): Bool { ### Test Your Contract with Forked State -Create `tests/token_checker_test.cdc`: +Create `cadence/tests/token_checker_test.cdc`: -```cadence tests/token_checker_test.cdc +```cadence cadence/tests/token_checker_test.cdc import Test access(all) fun setup() { // Deploy TokenChecker to the test account let err = Test.deployContract( name: "TokenChecker", - path: "cadence/contracts/TokenChecker.cdc", + path: "../contracts/TokenChecker.cdc", arguments: [] ) Test.expect(err, Test.beNil()) @@ -317,8 +334,8 @@ access(all) fun setup() { access(all) fun testCheckBalanceOnRealAccount() { // Test against a real mainnet account (Flow service account) let scriptResult = Test.executeScript( - Test.readFile("cadence/scripts/CheckBalance.cdc"), - [0x1654653399040a61] // Flow service account on mainnet + Test.readFile("../scripts/CheckBalance.cdc"), + [Address(0x1654653399040a61)] // Flow service account on mainnet ) Test.expect(scriptResult, Test.beSucceeded()) @@ -330,14 +347,14 @@ access(all) fun testCheckBalanceOnRealAccount() { access(all) fun testHasMinimumBalance() { let scriptResult = Test.executeScript( - Test.readFile("cadence/scripts/HasMinimumBalance.cdc"), - [0x1654653399040a61, 1000.0] + Test.readFile("../scripts/HasMinimumBalance.cdc"), + [Address(0x1654653399040a61), 1.0] ) Test.expect(scriptResult, Test.beSucceeded()) let hasMinimum = scriptResult.returnValue! as! Bool - Test.assert(hasMinimum == true, message: "Service account should have at least 1000 FLOW") + Test.assert(hasMinimum == true, message: "Service account should have at least 1 FLOW") } ``` @@ -367,7 +384,7 @@ import "FungibleToken" import "FlowToken" transaction { - prepare(signer: &Account) { + prepare(signer: auth(Storage, Capabilities) &Account) { if signer.storage.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault) == nil { signer.storage.save(<-FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>()), to: /storage/flowTokenVault) let cap = signer.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault) @@ -387,7 +404,7 @@ import "FlowToken" transaction(amount: UFix64, to: Address) { let sentVault: @{FungibleToken.Vault} - prepare(signer: &Account) { + prepare(signer: auth(Storage) &Account) { let vaultRef = signer.storage.borrow( from: /storage/flowTokenVault ) ?? panic("Could not borrow reference to the owner's Vault") @@ -408,7 +425,7 @@ transaction(amount: UFix64, to: Address) { ### Test Transaction Execution with Impersonation -Add this test function to the existing `tests/token_checker_test.cdc` file: +Add this test function to the existing `cadence/tests/token_checker_test.cdc` file: ```cadence access(all) fun testTransactionAsMainnetAccount() { @@ -418,7 +435,7 @@ access(all) fun testTransactionAsMainnetAccount() { // Check initial balance let initialBalanceScript = Test.executeScript( - Test.readFile("cadence/scripts/CheckBalance.cdc"), + Test.readFile("../scripts/CheckBalance.cdc"), [serviceAccount.address] ) Test.expect(initialBalanceScript, Test.beSucceeded()) @@ -430,7 +447,7 @@ access(all) fun testTransactionAsMainnetAccount() { // Set up the recipient's FlowToken vault let setupResult = Test.executeTransaction( Test.Transaction( - code: Test.readFile("cadence/transactions/SetupFlowTokenVault.cdc"), + code: Test.readFile("../transactions/SetupFlowTokenVault.cdc"), authorizers: [recipient.address], signers: [recipient], arguments: [] @@ -442,7 +459,7 @@ access(all) fun testTransactionAsMainnetAccount() { // This works because fork testing allows impersonating any account let txResult = Test.executeTransaction( Test.Transaction( - code: Test.readFile("cadence/transactions/TransferTokens.cdc"), + code: Test.readFile("../transactions/TransferTokens.cdc"), authorizers: [serviceAccount.address], signers: [serviceAccount], arguments: [10.0, recipient.address] @@ -453,7 +470,7 @@ access(all) fun testTransactionAsMainnetAccount() { // Verify the sender's balance decreased let newBalanceScript = Test.executeScript( - Test.readFile("cadence/scripts/CheckBalance.cdc"), + Test.readFile("../scripts/CheckBalance.cdc"), [serviceAccount.address] ) Test.expect(newBalanceScript, Test.beSucceeded()) @@ -464,12 +481,13 @@ access(all) fun testTransactionAsMainnetAccount() { // Verify the recipient received the tokens let recipientBalanceScript = Test.executeScript( - Test.readFile("cadence/scripts/CheckBalance.cdc"), + Test.readFile("../scripts/CheckBalance.cdc"), [recipient.address] ) Test.expect(recipientBalanceScript, Test.beSucceeded()) let recipientBalance = recipientBalanceScript.returnValue! as! UFix64 - Test.assertEqual(10.0, recipientBalance) + // Recipient should have at least 10.0 (may be slightly more due to storage refunds) + Test.assert(recipientBalance >= 10.0, message: "Recipient should have at least 10 FLOW") } ``` @@ -486,16 +504,16 @@ access(all) fun testTransactionAsMainnetAccount() { Now that you have multiple test files, run them all against the forked network: ```zsh -flow test --fork +flow test --fork mainnet ``` -This runs all `*_test.cdc` files in your project against mainnet by default. You should see: +This runs all `*_test.cdc` files in your project against mainnet. You should see: ``` -Test results: "tests/flow_token_test.cdc" +Test results: "cadence/tests/flow_token_test.cdc" - PASS: testFlowTokenSupplyIsPositive -Test results: "tests/token_checker_test.cdc" +Test results: "cadence/tests/token_checker_test.cdc" - PASS: testCheckBalanceOnRealAccount - PASS: testHasMinimumBalance - PASS: testTransactionAsMainnetAccount @@ -525,13 +543,13 @@ Fork tests run against Flow chain state only: - Run specific files or directories: ```zsh -flow test tests/flow_token_test.cdc tests/token_checker_test.cdc tests/subsuite/ +flow test cadence/tests/flow_token_test.cdc cadence/tests/token_checker_test.cdc --fork mainnet ``` - Optional: narrow by function name with `--name`: ```zsh -flow test tests/token_checker_test.cdc --name _smoke +flow test cadence/tests/token_checker_test.cdc --name _smoke --fork mainnet ``` - Optional: suffix a few functions with `_smoke` for quick PR runs; run the full suite nightly or on protected branches. From 17dad9820ad3f77bbfa71959d7d419c7cf5dcabe Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Tue, 28 Oct 2025 14:03:50 -0400 Subject: [PATCH 14/23] Apply suggestion from @briandoyle81 --- docs/build/cadence/smart-contracts/testing-strategy.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index f1486d7bcc..b88a899753 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -32,6 +32,7 @@ keywords: # Testing Smart Contracts A single, pragmatic strategy for testing on Flow. Use layers that are deterministic and isolated by default, add realism with forks when needed, and keep a minimal set of live network checks before release. + ## At a glance - **Unit & Property — Test Framework**: Hermetic correctness and invariants From e79e8dab91b7c7114817b01a5c3c19a83954758f Mon Sep 17 00:00:00 2001 From: Brian Doyle Date: Tue, 28 Oct 2025 14:20:42 -0400 Subject: [PATCH 15/23] Apply suggestion from @briandoyle81 --- docs/build/cadence/smart-contracts/testing-strategy.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index b88a899753..cdfa4c0628 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -118,8 +118,6 @@ See also: [Flow Networks]. - Diff event/resource shapes against your stored samples - Check access-node health and CI parallelism/sharding - - ## Do / Don’t - **Do**: Keep a fast, hermetic base; pin forks; tag tests; maintain tiny PR smoke sets; document pins and set a simple refresh schedule (e.g., after each spork or monthly) From 1dc0661622a4d6ff56d24da5006a6c5637ea3eda Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 12:42:43 -0700 Subject: [PATCH 16/23] address feedback --- docs/build/cadence/smart-contracts/testing.md | 6 +++--- docs/build/tools/emulator/index.md | 15 +++++++++++++++ docs/build/tools/flow-cli/tests.md | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/docs/build/cadence/smart-contracts/testing.md b/docs/build/cadence/smart-contracts/testing.md index ece3fe4014..271d345879 100644 --- a/docs/build/cadence/smart-contracts/testing.md +++ b/docs/build/cadence/smart-contracts/testing.md @@ -18,9 +18,9 @@ keywords: Testing is an essential part of smart contract development to ensure the correctness and reliability of your code. The Cadence Testing Framework provides a convenient way to write tests for your contracts, scripts and transactions which allows you to verify the functionality and correctness of your smart contracts. - -Looking for high‑level guidance on when to use emulator, forks, or testnet? See Testing Smart Contracts. - +:::info +Looking for high‑level guidance on when to use emulator, forks, or testnet? See [Testing Smart Contracts](./testing-strategy.md). +::: ## Install Flow CLI diff --git a/docs/build/tools/emulator/index.md b/docs/build/tools/emulator/index.md index c15bf556ec..06e1a2017b 100644 --- a/docs/build/tools/emulator/index.md +++ b/docs/build/tools/emulator/index.md @@ -178,6 +178,21 @@ flow emulator --help The Flow CLI provides a command to create emulator snapshots, which are points in blockchain history you can later jump to and reset the state to that moment. This can be useful for testing where you establish a beginning state, run tests and after revert back to the initial state. +### Quick snapshot workflow + +```bash +# 1) Start the emulator with snapshots enabled (in a separate terminal) +flow emulator --snapshot + +# 2) Create a snapshot at the current state +flow emulator snapshot create baseline + +# 3) Make changes, run tests, etc. + +# 4) Reset the emulator back to the snapshot +flow emulator snapshot load baseline +``` + ### Create a new snapshot Create a new emulator snapshot at the current block with a name of `myInitialState`. diff --git a/docs/build/tools/flow-cli/tests.md b/docs/build/tools/flow-cli/tests.md index a476c269d6..b9d8c2bdf8 100644 --- a/docs/build/tools/flow-cli/tests.md +++ b/docs/build/tools/flow-cli/tests.md @@ -296,7 +296,7 @@ See public access node URLs in [Flow Networks](../../../protocol/flow-networks/i - Type: `uint64` - Default: `0` -Pin the fork to a specific block height for historical state testing. Only data from the current spork is available via public access nodes. +Pin the fork to a specific block height for historical state testing. Only blocks from the current spork (since the most recent network upgrade) are available via public access nodes; earlier blocks are not accessible via public access nodes. ```shell flow test --fork mainnet --fork-height 85432100 From 6afdbbb0dfee2bf484caad7fdb100cef563d1b6b Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 13:54:19 -0700 Subject: [PATCH 17/23] Add better use case info to testing contracts doc --- .../smart-contracts/testing-strategy.md | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index cdfa4c0628..c7a2c885da 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -72,7 +72,33 @@ See also: [Fork Testing with Cadence], [Fork Testing Flags]. - **Use when**: Driving dapps, wallets, bots, indexers, or exploratory debugging outside the test framework - **Why**: Production-like state with local, disposable control; great for E2E and migrations - **Run**: Dev machines and focused E2E CI jobs -- **Notes**: Pin height; run on dedicated ports; impersonation is built-in; mutations are local; off-chain/oracle calls are not live—mock or run local stubs +- **Notes**: + - Pin height; run on dedicated ports; impersonation is built-in; mutations are local; off-chain/oracle calls are not live—mock or run local stubs + - What to run: Manual exploration and debugging of flows against a forked state; frontend connected to the emulator (e.g., `npm run dev` pointed at `http://localhost:8888`); automated E2E/FE suites (e.g., Cypress/Playwright) against the local fork; headless clients, wallets/bots/indexers, and migration scripts + - Not for the canonical Cadence test suite—prefer `flow test --fork` for scripted Cadence tests (see [Fork Testing Flags] and [Running Cadence Tests]) + + Quick start example: + + ```bash + # Start a fork (pinning height recommended for reproducibility) + flow emulator --fork mainnet --fork-height + ``` + + ```javascript + // Configure FCL for the emulator + import { config } from "@onflow/fcl"; + config({ + "accessNode.api": "http://localhost:8888" + }); + ``` + + ```bash + # Run app + npm run dev + + # Run E2E tests + npx cypress run + ``` See also: [Flow Emulator]. @@ -81,7 +107,28 @@ See also: [Flow Emulator]. - **Use when**: Final network plumbing and configuration checks before release - **Why**: Validates infra differences you cannot fully simulate - **Run**: Pre-release and on infra changes -- **Notes**: Keep canaries minimal and time-boxed; protocol/partner support may be limited on testnet (not all third-party contracts are deployed or up to date) +- **Notes**: + - Keep canaries minimal and time-boxed; protocol/partner support may be limited on testnet (not all third-party contracts are deployed or up to date) + - What to run: Minimal app smoke tests (login/auth, key flows, mint/transfer, event checks); frontend connected to Testnet with a small Cypress/Playwright smoke set; infra/config checks (endpoints, contract addresses/aliases, env vars, service/test accounts) + - Not for the canonical Cadence test suite — prefer `flow test --fork` for scripted tests (see [Fork Testing Flags] and [Running Cadence Tests]) + + Quick start example: + + ```javascript + // Configure FCL for Testnet + import { config } from "@onflow/fcl"; + config({ + "accessNode.api": "https://rest-testnet.onflow.org" + }); + ``` + + ```bash + # Run app + npm run dev + + # Run smoke tests + npx cypress run --spec "cypress/e2e/smoke.*" + ``` See also: [Flow Networks]. From 90b4704555ac0e72929166c80ea84bf576024090 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink <17958158+jribbink@users.noreply.github.com> Date: Tue, 28 Oct 2025 14:59:32 -0700 Subject: [PATCH 18/23] Update docs/build/tools/flow-cli/tests.md --- docs/build/tools/flow-cli/tests.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/build/tools/flow-cli/tests.md b/docs/build/tools/flow-cli/tests.md index b9d8c2bdf8..429778a49c 100644 --- a/docs/build/tools/flow-cli/tests.md +++ b/docs/build/tools/flow-cli/tests.md @@ -273,10 +273,6 @@ Requirements: - The network must exist in `flow.json` - The network must have a valid `host` configured -Common errors: - -- `network "" not found in flow.json` → add the network definition -- `network "" has no host configured` → set the `host` field #### --fork-host From 4d98426b804cee11e3879694cbebc86fbc58a050 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink <17958158+jribbink@users.noreply.github.com> Date: Tue, 28 Oct 2025 14:59:56 -0700 Subject: [PATCH 19/23] Update docs/build/tools/flow-cli/tests.md --- docs/build/tools/flow-cli/tests.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/build/tools/flow-cli/tests.md b/docs/build/tools/flow-cli/tests.md index 429778a49c..57af647155 100644 --- a/docs/build/tools/flow-cli/tests.md +++ b/docs/build/tools/flow-cli/tests.md @@ -273,7 +273,6 @@ Requirements: - The network must exist in `flow.json` - The network must have a valid `host` configured - #### --fork-host - Type: `string` From fc33568f465347798afcba0ee1a7e704493afc01 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 15:25:14 -0700 Subject: [PATCH 20/23] minor edits --- .../cadence/fork-testing/index.md | 24 +++++++-------- .../smart-contracts/testing-strategy.md | 30 ++++++++++++------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index ff0ea803a4..a3c596dc71 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -208,27 +208,23 @@ You should see the test PASS. If not, verify your network host in `flow.json` an Now you'll create a contract that depends on FlowToken and test it against the forked mainnet state—no need to bootstrap tokens or set up test accounts. -### Generate a Key Pair +### Create a Test Account -Generate a key pair that will be used for your test contract's mainnet alias: +Create a new account for deploying your contract: ```zsh -flow keys generate +flow accounts create ``` -This will output a public/private key pair. Save the **private key** to a file: +Follow the prompts: +- Select "mainnet" for the network +- Name your account as desired -```zsh -echo "YOUR_PRIVATE_KEY_HERE" > mainnet-test.pkey -``` +This will output the new account address. Use this address as the mainnet alias for your contract in flow.json. -Note the **public key** - you'll need it to derive an account address. For fork testing, any valid Flow address format works. You can use this command to generate a test address from your key: - -```zsh -flow accounts derive-address mainnet-test.pkey -``` - -Or simply use a placeholder mainnet-format address like `f8d6e0586b0a20c7` for testing purposes. +:::note +This creates a local account with a mainnet-format address for fork testing. When you're ready to deploy to actual mainnet, you'll use this same account—see the [Deploying Contracts guide](../../build/cadence/smart-contracts/deploying.md) for details. +::: ### Create a Contract that Uses FlowToken diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index c7a2c885da..8aecd61759 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -85,11 +85,16 @@ See also: [Fork Testing with Cadence], [Fork Testing Flags]. ``` ```javascript - // Configure FCL for the emulator - import { config } from "@onflow/fcl"; - config({ - "accessNode.api": "http://localhost:8888" - }); + // In your root component (e.g., App.tsx) + import { FlowProvider } from "@onflow/react-sdk"; + + function App() { + return ( + + {/* Your app components */} + + ); + } ``` ```bash @@ -115,11 +120,16 @@ See also: [Flow Emulator]. Quick start example: ```javascript - // Configure FCL for Testnet - import { config } from "@onflow/fcl"; - config({ - "accessNode.api": "https://rest-testnet.onflow.org" - }); + // In your root component (e.g., App.tsx) + import { FlowProvider } from "@onflow/react-sdk"; + + function App() { + return ( + + {/* Your app components */} + + ); + } ``` ```bash From 5d116b67e5699a5e8d4e6cdce469136b37350519 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 15:25:25 -0700 Subject: [PATCH 21/23] remove "(Interactive)" from header --- docs/build/cadence/smart-contracts/testing-strategy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build/cadence/smart-contracts/testing-strategy.md b/docs/build/cadence/smart-contracts/testing-strategy.md index 8aecd61759..510f4552a0 100644 --- a/docs/build/cadence/smart-contracts/testing-strategy.md +++ b/docs/build/cadence/smart-contracts/testing-strategy.md @@ -67,7 +67,7 @@ See also: [Running Cadence Tests]. See also: [Fork Testing with Cadence], [Fork Testing Flags]. -### Local Integration Sandbox (Interactive) — `flow emulator --fork` +### Local Integration Sandbox — `flow emulator --fork` - **Use when**: Driving dapps, wallets, bots, indexers, or exploratory debugging outside the test framework - **Why**: Production-like state with local, disposable control; great for E2E and migrations From 208a414d5987c4b2e255f228f7b86a7bdee61533 Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 15:34:42 -0700 Subject: [PATCH 22/23] cleanup tutorial file naming & generation --- .../cadence/fork-testing/index.md | 68 ++++++++++++------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index a3c596dc71..8faf058e92 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -147,13 +147,13 @@ Your `flow.json` should now have the mainnet and testnet networks configured fro ## Test Reading Live State -The test directories are already created by `flow init`. If needed, create the scripts directory: +Generate a script to read FlowToken supply: ```zsh -mkdir -p cadence/scripts +flow generate script GetFlowTokenSupply ``` -First, create a script to read FlowToken supply. Create `cadence/scripts/GetFlowTokenSupply.cdc`: +Open `cadence/scripts/GetFlowTokenSupply.cdc` and replace its contents with: ```cadence cadence/scripts/GetFlowTokenSupply.cdc import "FlowToken" @@ -163,9 +163,15 @@ access(all) fun main(): UFix64 { } ``` -Now create the test file `cadence/tests/flow_token_test.cdc`: +Generate the test file: -```cadence cadence/tests/flow_token_test.cdc +```zsh +flow generate test FlowToken +``` + +Open `cadence/tests/FlowToken_test.cdc` and replace its contents with: + +```cadence cadence/tests/FlowToken_test.cdc import Test access(all) fun testFlowTokenSupplyIsPositive() { @@ -193,13 +199,13 @@ Notes: Run just this test file against a fork to confirm your setup works: ```zsh -flow test cadence/tests/flow_token_test.cdc --fork mainnet +flow test cadence/tests/FlowToken_test.cdc --fork mainnet ``` Target testnet instead: ```zsh -flow test cadence/tests/flow_token_test.cdc --fork testnet +flow test cadence/tests/FlowToken_test.cdc --fork testnet ``` You should see the test PASS. If not, verify your network host in `flow.json` and that dependencies are installed. @@ -276,21 +282,24 @@ Update your `flow.json` to include the contract with aliases, using the address }, "accounts": { "mainnet-test": { - "address": "", - "key": { - "type": "file", - "location": "mainnet-test.pkey" - } + "address": "" } } } ``` -The `Test.deployContract` function will automatically deploy your contract to the testing environment during test execution. +Note: No local private key is required for forked tests. The accounts entry above is included so you can copy/reference the address in your config; keys can be omitted for fork tests. Contracts deploy to the testing environment at `testing` alias, and transactions that interact with forked state can use impersonation. The `Test.deployContract` function will automatically deploy your contract to the testing environment during test execution. ### Create Scripts for Testing -Create `cadence/scripts/CheckBalance.cdc`: +Generate the scripts: + +```zsh +flow generate script CheckBalance +flow generate script HasMinimumBalance +``` + +Open `cadence/scripts/CheckBalance.cdc` and replace its contents with: ```cadence cadence/scripts/CheckBalance.cdc import "TokenChecker" @@ -300,7 +309,7 @@ access(all) fun main(addr: Address): UFix64 { } ``` -Create `cadence/scripts/HasMinimumBalance.cdc`: +Open `cadence/scripts/HasMinimumBalance.cdc` and replace its contents with: ```cadence cadence/scripts/HasMinimumBalance.cdc import "TokenChecker" @@ -312,9 +321,15 @@ access(all) fun main(addr: Address, min: UFix64): Bool { ### Test Your Contract with Forked State -Create `cadence/tests/token_checker_test.cdc`: +Generate the test file: + +```zsh +flow generate test TokenChecker +``` + +Open `cadence/tests/TokenChecker_test.cdc` and replace its contents with: -```cadence cadence/tests/token_checker_test.cdc +```cadence cadence/tests/TokenChecker_test.cdc import Test access(all) fun setup() { @@ -367,13 +382,14 @@ Fork testing includes built-in account impersonation—you can execute transacti ### Create Transactions -Create the transactions directory: +Generate the transactions: ```zsh -mkdir -p cadence/transactions +flow generate transaction SetupFlowTokenVault +flow generate transaction TransferTokens ``` -First, create a transaction to set up a FlowToken vault. Create `cadence/transactions/SetupFlowTokenVault.cdc`: +Open `cadence/transactions/SetupFlowTokenVault.cdc` and replace its contents with: ```cadence cadence/transactions/SetupFlowTokenVault.cdc import "FungibleToken" @@ -391,7 +407,7 @@ transaction { } ``` -Now create the transfer transaction. Create `cadence/transactions/TransferTokens.cdc`: +Open `cadence/transactions/TransferTokens.cdc` and replace its contents with: ```cadence cadence/transactions/TransferTokens.cdc import "FungibleToken" @@ -421,7 +437,7 @@ transaction(amount: UFix64, to: Address) { ### Test Transaction Execution with Impersonation -Add this test function to the existing `cadence/tests/token_checker_test.cdc` file: +Add this test function to the existing `cadence/tests/TokenChecker_test.cdc` file: ```cadence access(all) fun testTransactionAsMainnetAccount() { @@ -506,10 +522,10 @@ flow test --fork mainnet This runs all `*_test.cdc` files in your project against mainnet. You should see: ``` -Test results: "cadence/tests/flow_token_test.cdc" +Test results: "cadence/tests/FlowToken_test.cdc" - PASS: testFlowTokenSupplyIsPositive -Test results: "cadence/tests/token_checker_test.cdc" +Test results: "cadence/tests/TokenChecker_test.cdc" - PASS: testCheckBalanceOnRealAccount - PASS: testHasMinimumBalance - PASS: testTransactionAsMainnetAccount @@ -539,13 +555,13 @@ Fork tests run against Flow chain state only: - Run specific files or directories: ```zsh -flow test cadence/tests/flow_token_test.cdc cadence/tests/token_checker_test.cdc --fork mainnet +flow test cadence/tests/FlowToken_test.cdc cadence/tests/TokenChecker_test.cdc --fork mainnet ``` - Optional: narrow by function name with `--name`: ```zsh -flow test cadence/tests/token_checker_test.cdc --name _smoke --fork mainnet +flow test cadence/tests/TokenChecker_test.cdc --name _smoke --fork mainnet ``` - Optional: suffix a few functions with `_smoke` for quick PR runs; run the full suite nightly or on protected branches. From d085ba1743945885d2da00e2dd2bae044c853dff Mon Sep 17 00:00:00 2001 From: Jordan Ribbink Date: Tue, 28 Oct 2025 16:00:50 -0700 Subject: [PATCH 23/23] fix build errors --- .../cadence/fork-testing/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md index 8faf058e92..3475e1e2ff 100644 --- a/docs/blockchain-development-tutorials/cadence/fork-testing/index.md +++ b/docs/blockchain-development-tutorials/cadence/fork-testing/index.md @@ -229,7 +229,7 @@ Follow the prompts: This will output the new account address. Use this address as the mainnet alias for your contract in flow.json. :::note -This creates a local account with a mainnet-format address for fork testing. When you're ready to deploy to actual mainnet, you'll use this same account—see the [Deploying Contracts guide](../../build/cadence/smart-contracts/deploying.md) for details. +This creates a local account with a mainnet-format address for fork testing. When you're ready to deploy to actual mainnet, you'll use this same account—see the [Deploying Contracts guide](pathname:///build/cadence/smart-contracts/deploying) for details. ::: ### Create a Contract that Uses FlowToken @@ -541,14 +541,14 @@ See also: - Emulator (fork mode for interactive E2E): [Flow Emulator] - Networks and access nodes: [Flow Networks] -::::info +:::info External oracles and off-chain systems Fork tests run against Flow chain state only: - No live off-chain/API calls or cross-chain reads - Price feeds, bridges, indexers, and similar must be mocked (stub contracts or fixtures) - For end-to-end, combine with `flow emulator --fork` and a local stub service -:::: +::: ### Select tests quickly