Rust区块链开发库pallet-revive-fixtures的使用:Substrate框架中的测试工具与固定数据生成插件

Rust区块链开发库pallet-revive-fixtures的使用:Substrate框架中的测试工具与固定数据生成插件

安装

在项目目录中运行以下Cargo命令:

cargo add pallet-revive-fixtures

或者在Cargo.toml中添加以下行:

pallet-revive-fixtures = "0.5.0"

基本使用

pallet-revive-fixtures是一个用于Substrate框架的测试工具和固定数据生成插件,主要用于区块链开发中的测试场景。以下是使用示例:

use pallet_revive_fixtures::*;
use frame_support::{assert_ok, traits::OnInitialize};

#[test]
fn test_fixture_initialization() {
    // 创建测试环境
    new_test_ext().execute_with(|| {
        // 初始化区块
        run_to_block(1);
        
        // 使用固定数据生成器
        let account = fixture_account("Alice");
        let balance = fixture_balance(1000);
        
        // 断言测试
        assert_ok!(SomePallet::do_something(account, balance));
        
        // 运行到指定区块
        run_to_block(10);
        
        // 验证状态
        assert_eq!(SomePallet::some_value(), expected_value);
    });
}

完整示例

以下是一个更完整的测试用例示例,展示了如何使用pallet-revive-fixtures进行复杂的区块链测试:

use pallet_revive_fixtures::*;
use frame_support::{assert_ok, assert_noop};
use sp_runtime::traits::BadOrigin;

mod mock {
    use super::*;
    
    frame_support::construct_runtime!(
        pub enum TestRuntime where
            Block = Block,
            NodeBlock = Block,
            UncheckedExtrinsic = UncheckedExtrinsic,
        {
            System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
            Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
            MyPallet: pallet_my_pallet::{Pallet, Call, Storage, Event<T>},
        }
    );
    
    impl pallet_my_pallet::Config for TestRuntime {
        type Event = Event;
        type Currency = Balances;
    }
}

use mock::*;

#[test]
fn comprehensive_pallet_test() {
    new_test_ext().execute_with(|| {
        // 初始化测试环境
        let alice = fixture_account("Alice");
        let bob = fixture_account("Bob");
        let charlie = fixture_account("Charlie");
        
        // 设置初始余额
        let initial_balance = fixture_balance(1000);
        assert_ok!(Balances::set_balance(RuntimeOrigin::root(), alice, initial_balance, 0));
        assert_ok!(Balances::set_balance(RuntimeOrigin::root(), bob, initial_balance, 0));
        
        // 测试正常操作
        assert_ok!(MyPallet::do_operation(RuntimeOrigin::signed(alice), bob, 500));
        
        // 验证状态变化
        assert_eq!(MyPallet::some_storage_value(), expected_value);
        assert_eq!(Balances::free_balance(&alice), 500);
        assert_eq!(Balances::free_balance(&bob), 1500);
        
        // 测试错误情况
        assert_noop!(
            MyPallet::do_operation(RuntimeOrigin::signed(charlie), alice, 100),
            BadOrigin
        );
        
        // 测试事件
        System::assert_last_event(
            Event::MyPallet(crate::Event::OperationCompleted { from: alice, to: bob, amount: 500 })
        );
        
        // 运行多个区块测试时间相关逻辑
        run_to_block(10);
        assert_ok!(MyPallet::time_sensitive_operation(RuntimeOrigin::signed(alice)));
        
        run_to_block(20);
        assert_eq!(MyPallet::get_time_dependent_value(), expected_value_at_block_20);
    });
}

主要功能

  1. 测试环境设置new_test_ext()创建测试环境
  2. 区块模拟run_to_block(n)模拟运行到指定区块
  3. 固定数据生成
    • fixture_account(name)生成测试账户
    • fixture_balance(amount)生成固定金额
  4. 断言辅助:简化常见断言操作
  5. 事件验证:方便验证事件是否触发

许可证

本库采用GPL-3.0-only许可证。


1 回复

Rust区块链开发库pallet-revive-fixtures的使用:Substrate框架中的测试工具与固定数据生成插件

概述

pallet-revive-fixtures是Substrate框架中的一个实用工具库,主要用于简化区块链开发中的测试流程和固定数据(fixtures)生成。它为开发者提供了便捷的方法来创建测试环境和预定义数据,特别适合在开发Substrate pallet时使用。

主要功能

  1. 测试环境搭建:快速创建区块链运行时环境
  2. 固定数据生成:预定义测试数据模板
  3. 账户管理:测试账户的创建和管理
  4. 区块生成:模拟区块生成和交易处理

安装方法

在项目的Cargo.toml中添加依赖:

[dependencies]
pallet-revive-fixtures = { git = "https://github.com/revive-network/pallet-revive-fixtures.git", branch = "main" }

基本使用方法

1. 初始化测试环境

use pallet_revive_fixtures::TestRuntime;
use frame_support::construct_runtime;

construct_runtime!(
    pub enum TestRuntime where
        Block = Block,
        NodeBlock = Block,
        UncheckedExtrinsic = UncheckedExtrinsic,
    {
        System: frame_system,
        // 添加你的其他pallet
        ReviveFixtures: pallet_revive_fixtures,
    }
);

2. 创建测试账户

use pallet_revive_fixtures::accounts;

let alice = accounts::alice();
let bob = accounts::bob();
let charlie = accounts::charlie();

3. 使用固定数据

use pallet_revive_fixtures::fixtures;

// 获取预定义的固定数据
let default_fixtures = fixtures::default();

// 使用自定义数据
let custom_fixtures = fixtures::custom()
    .with_account("dave", 1000)
    .with_balance("eve", 2000);

4. 在测试中使用

#[test]
fn test_my_pallet_function() {
    // 初始化测试环境
    let mut t = TestRuntime::new_with_fixtures(fixtures::default());
    
    // 执行测试逻辑
    t.execute_with(|| {
        // 这里可以调用你的pallet函数进行测试
        assert_ok!(MyPallet::some_function(Origin::signed(accounts::alice())));
    });
}

高级用法

自定义固定数据模板

use pallet_revive_fixtures::{FixtureBuilder, AccountId, Balance};

let my_fixtures = FixtureBuilder::new()
    .add_account(AccountId::new([1; 32]), Balance::from(1000))
    .add_account(AccountId::new([2; 32]), Balance::from(2000))
    .build();

模拟区块生成

use pallet_revive-fixtures::BlockSimulator;

let mut simulator = BlockSimulator::new(TestRuntime::new_with_fixtures(fixtures::default()));

// 模拟生成10个区块
simulator.generate_blocks(10);

// 在特定区块高度执行操作
simulator.at_block(5, || {
    // 在第5个区块执行的操作
});

完整示例:测试投票pallet

下面是一个使用pallet-revive-fixtures测试投票pallet的完整示例:

use frame_support::{assert_ok, assert_err, traits::{Currency, OnInitialize}};
use frame_system::RawOrigin;
use pallet_revive_fixtures::{TestRuntime, accounts, fixtures};

// 定义测试运行时
pub type AccountId = <TestRuntime as frame_system::Config>::AccountId;
pub type Balance = <<TestRuntime as pallet_balances::Config>::Currency as Currency<AccountId>>::Balance;

#[test]
fn test_voting_pallet() {
    // 设置初始测试数据 - 3个账户,每个账户有1000代币
    let fixtures = fixtures::custom()
        .with_balance(accounts::alice(), 1000)
        .with_balance(accounts::bob(), 1000)
        .with_balance(accounts::charlie(), 1000);
    
    // 初始化测试环境
    let mut t = TestRuntime::new_with_fixtures(fixtures);
    
    t.execute_with(|| {
        // 创建提案
        assert_ok!(VotingPallet::create_proposal(
            Origin::signed(accounts::alice()),
            "Proposal 1".into(),
            100, // 通过所需票数
            10   // 投票持续时间(区块数)
        ));
        
        // 检查提案状态
        let proposal = VotingPallet::proposals(0).unwrap();
        assert_eq!(proposal.title, "Proposal 1");
        assert_eq!(proposal.required_votes, 100);
        
        // 进行投票
        assert_ok!(VotingPallet::vote(
            Origin::signed(accounts::bob()),
            0,  // 提案ID
            true, // 赞成
            50   // 投票权重
        ));
        
        // 检查投票结果
        let votes = VotingPallet::proposal_votes(0);
        assert_eq!(votes.yes_votes, 50);
        
        // 模拟区块前进
        let mut simulator = BlockSimulator::new(t);
        simulator.generate_blocks(15); // 超过投票期限
        
        // 在区块高度15检查提案状态
        simulator.at_block(15, || {
            let proposal = VotingPallet::proposals(0).unwrap();
            assert!(proposal.is_concluded);
            assert!(!proposal.is_passed); // 50 < 100,未通过
        });
    });
}

注意事项

  1. 该库主要用于测试环境,不建议在生产环境中使用
  2. 固定数据应根据实际测试需求进行定制
  3. 在复杂场景中,可能需要结合其他测试工具一起使用
  4. 注意及时更新库版本以获取最新功能和修复

通过使用pallet-revive-fixtures,开发者可以显著简化Substrate pallet的测试流程,提高开发效率和测试覆盖率。

回到顶部