菜单

测试基础设施

相关源文件

目的

本页概述了 Sway 编程语言中的测试基础设施。该测试基础设施使开发人员能够验证 Sway 程序、合约以及与 Fuel VM 交互的正确性。有关合约特定测试的信息,请参阅合约测试;有关整个工具链端到端测试的信息,请参阅端到端测试

架构概述

该测试基础设施涵盖多个层面,从编译器组件的单元测试到验证 Fuel VM 上合约交互的端到端测试。

来源:test/Cargo.toml1-45

测试框架和依赖项

Sway 测试基础设施依赖于多个关键依赖项,以支持不同类型的测试

依赖项目的
forc-test提供用于测试 Sway 合约的工具
insta支持编译器输出的快照测试
libtest-mimic实现了一个类似于 Rust 内置测试框架的测试运行器
filecheck根据预期模式验证文件内容
fuel-vm模拟 Fuel VM 进行合约测试
forc-client与已部署的合约交互

来源:test/Cargo.toml8-44

测试类别

编译器单元测试

这些测试验证 Sway 编译器工具链中各个组件的正确性。它们使用 Rust 编写,并采用 Rust 的标准测试框架。

合约集成测试

合约集成测试验证合约能否成功部署以及合约交互是否按预期工作。这些测试通常会:

  1. 通过 ID 引用预部署的合约
  2. 创建一个 ABI 实例以与合约交互
  3. 调用合约方法并验证响应
  4. 断言结果与预期值匹配

来源:test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw1-42

合约测试结构

大多数合约测试遵循一致的模式,如下面的典型示例所示

script;
use some_contract_abi::SomeInterface;

// Contract ID depends on encoding configuration
#[cfg(experimental_new_encoding = false)]
const CONTRACT_ID = 0x...;
#[cfg(experimental_new_encoding = true)]
const CONTRACT_ID = 0x...; // AUTO-CONTRACT-ID ../../test_contracts/... --release

fn main() -> bool {
    // Create ABI instance
    let contract = abi(SomeInterface, CONTRACT_ID);
    
    // Call contract methods and verify results
    let result = contract.some_method();
    assert(result == expected_value);
    
    true
}

AUTO-CONTRACT-ID 注释指定了应部署合约的相对路径。这有助于自动化测试,其中合约被部署后,其 ID 会在测试脚本中自动更新。

来源:test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw1-35

按功能划分的测试类型

存储测试

存储测试验证合约能否正确存储和检索数据。它们调用与存储交互的合约方法,并断言检索到的值与存储的值匹配。

来源:test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw1-16 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw1-67

资产操作测试

这些测试验证合约中铸造、销毁、转移或以其他方式操作资产的功能。它们通常会:

  1. 调用合约上的资产操作方法
  2. 检查操作前后的余额
  3. 断言余额变化与预期值匹配

来源:test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw1-68 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw1-26

复杂数据结构测试

这些测试验证合约能否正确处理结构体、枚举和数组等复杂类型。它们将复杂数据结构传递给合约,并验证返回的数据保持完整性。

来源:test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw1-46 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw1-44 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw1-20

上下文和认证测试

这些测试验证与区块链上下文交互或实现认证机制的合约功能

来源:test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw1-78 test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw1-16

运行测试

可以使用 forc test 命令执行测试。确切的命令语法取决于您要测试的内容:

# Run all tests
forc test

# Run specific test
forc test path/to/test

# Run tests with specific features enabled
forc test --features="feature1,feature2"

最佳实践

  1. 隔离性:确保测试不依赖于其他测试的状态
  2. 集中测试:每个测试文件测试一个特定功能
  3. 配置处理:使用 #[cfg(...)] 指令处理不同的配置
  4. 初始状态:测试余额变化时,在操作前捕获初始状态
  5. 合约部署:使用 AUTO-CONTRACT-ID 机制确保测试针对正确的合约运行

来源:test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw34-35