3 个稳定版本
4.0.0 | 2024年7月3日 |
---|---|
3.0.1 | 2023年11月7日 |
3.0.0 | 2023年9月21日 |
#4 在 #tube
170KB
3K SLoC
coreum-test-tube
一个 CosmWasm x Coreum 集成测试库,与 cw-multi-test
不同,它允许您测试您的 cosmwasm 合约与真实链的逻辑,而不是模拟。
目录
入门指南
为了演示 coreum-test-tube
的工作原理,让我们用一个简单的示例合约:来自 cw-plus
的 cw-whitelist。
这是设置测试的方法
use cosmwasm_std::Coin;
use coreum_test_tube::CoreumTestApp;
// Create new Coreum appchain instance.
let app = CoreumTestApp::new();
// Create a new account with initial funds and one without initial funds
use coreum_test_tube::runner:app::FEE_DENOM;
let signer = app
.init_account(&[Coin::new(100_000_000_000_000_000_000u128, FEE_DENOM)])
.unwrap();
let user = app.init_account(&[]).unwrap();
现在我们有 appchain 实例和两个账户,让我们与链交互。这不会运行 Docker 实例或启动外部进程,它只是将 appchain 的代码作为库加载并创建一个内存实例。
请注意,init_account
是一个便利函数,用于创建一个带有初始余额的账户。如果您想创建很多账户,可以使用 init_accounts
。该包中定义了大量的便利函数。
use cosmwasm_std::coins;
use coreum_test_tube::CoreumTestApp;
let app = CoreumTestApp::new();
let accounts = app
.init_accounts(&coins(100_000_000_000, FEE_DENOM), 4)
.unwrap();
let acc1 = accounts.get(0).unwrap();
let acc2 = accounts.get(1).unwrap();
let acc3 = accounts.get(2).unwrap();
let acc4 = accounts.get(3).unwrap();
现在,如果我们想测试一个 cosmwasm 合约,我们需要
- 一个构建和优化的 wasm 文件(我们将使用放置在
test_artifacts
目录中的 cw1_whitelist.wasm 合约) - 存储代码
- 实例化
- 执行或查询
use cosmwasm_std::coins;
use cw1_whitelist::msg::{InstantiateMsg}; // for instantiating cw1_whitelist contract, which is already in a public crate
use coreum_test_tube::{Account, Module, CoreumTestApp, Wasm};
let app = CoreumTestApp::new();
let accs = app
.init_accounts(&coins(100_000_000_000, FEE_DENOM), 2)
.unwrap();
let account1 = &accs.get(0).unwrap();
let account2 = &accs.get(1).unwrap();;
为了测试我们的智能合约,我们首先需要构建一个优化的 wasm 文件,以便我们可以存储它。对于这个例子,正如已经提到的,我们将使用 cw1_whitelist,它已经在 test_artifacts
目录中编译。有关此合约的更多信息,您可以检查 cw-plus。
// `Wasm` is the module we use to interact with cosmwasm releated logic on the appchain
let wasm = Wasm::new(&app);
// Store compiled wasm code on the appchain and retrieve its code id
let wasm_byte_code = std::fs::read("./test_artifacts/cw1_whitelist.wasm").unwrap();
let code_id = wasm
.store_code(&wasm_byte_code, None, &signer)
.unwrap()
.data
.code_id;
// Instantiate contract with initial admin (signer) account defined beforehand and make admin list mutable
let contract_addr = wasm
.instantiate(
code_id,
&InstantiateMsg {
admins: vec![signer.address()],
mutable: true,
},
None,
"label".into(),
&[],
&signer,
)
.unwrap()
.data
.address;
// Execute the contract to modify admin to user address
wasm.execute::<ExecuteMsg>(
&contract_addr,
&ExecuteMsg::UpdateAdmins {
admins: vec![user.address()],
},
&vec![],
&signer,
)
.unwrap();
// Query the contract to verify that the admin has been updated correctly.
let admin_list = wasm
.query::<QueryMsg, AdminListResponse>(&contract_addr, &QueryMsg::AdminList {})
.unwrap();
assert_eq!(admin_list.admins, vec![user.address()]);
assert!(admin_list.mutable);
调试
在您的合约代码中,如果您想进行调试,可以使用deps.api.debug(..)
,这将把调试信息打印到标准输出。默认情况下,wasmd
已禁用此功能,但CoreumTestApp
允许标准输出输出,以便您可以在运行测试的同时调试智能合约。
使用模块包装器
在某些情况下,您可能想直接与appchain逻辑交互来设置环境或查询appchain的状态,而不是测试智能合约。模块包装器提供了方便的函数来与appchain的模块交互。您可以使用这些包装器与所有Coreum本地模块进行交互。
让我们尝试与AssetFT
模块交互,同时与本地Bank
模块交互。
use cosmwasm_std::Coin;
use coreum_test_tube::{Account, Module, CoreumTestApp, Bank, AssetFT};
let app = CoreumTestApp::new();
let signer = app
.init_account(&[Coin::new(100_000_000_000_000_000_000u128, FEE_DENOM)])
.unwrap();
let receiver = app
.init_account(&[Coin::new(100_000_000_000_000_000_000u128, FEE_DENOM)])
.unwrap();
// Create AssetFT Module Wrapper
let assetft = AssetFT::new(&app);
// Create Bank Module Wrapper
let bank = Bank::new(&app);
// Query the issue fee and assert if the fee is correct
let request_params = assetft.query_params(&QueryParamsRequest {}).unwrap();
assert_eq!(
request_params.params.unwrap().issue_fee.unwrap(),
BaseCoin {
amount: 10000000u128.to_string(),
denom: FEE_DENOM.to_string(),
}
);
// Issue a new native asset with the following information
assetft.
issue(
MsgIssue {
issuer: signer.address(),
symbol: "TEST".to_string(),
subunit: "utest".to_string(),
precision: 6,
initial_amount: "10".to_string(),
description: "test_description".to_string(),
features: vec![MINTING as i32],
burn_rate: "0".to_string(),
send_commission_rate: "0".to_string(),
uri: "test_uri".to_string(),
uri_hash: "test_uri_hash".to_string(),
},
&signer,
)
.unwrap();
// Query the new asset and verify that the initial_amount is correct.
let denom = format!("{}-{}", "utest", signer.address()).to_lowercase();
let request_balance = assetft
.query_balance(&QueryBalanceRequest {
account: signer.address(),
denom: denom.clone(),
})
.unwrap()
assert_eq!(request_balance.balance, "10".to_string());
// Mint additional tokens and verify that the balance has been updated correctly (10 + 990 = 1000)
assetft
.mint(
MsgMint {
sender: signer.address(),
coin: Some(BaseCoin {
denom: denom.clone(),
amount: "990".to_string(),
}),
recipient: signer.address(),
},
&signer,
)
.unwrap()
let request_balance = assetft
.query_balance(&QueryBalanceRequest {
account: signer.address(),
denom: denom.clone(),
})
.unwrap()
assert_eq!(request_balance.balance, "1000".to_string());
// Using the bank module, send a transaction to another address and verify that both balances of the AssetFTs have been updated correctly.
bank.send(
MsgSend {
from_address: signer.address(),
to_address: receiver.address(),
amount: vec![BaseCoin {
amount: "100".to_string(),
denom: denom.clone(),
}],
},
&signer,
)
.unwrap()
let request_balance = assetft
.query_balance(&QueryBalanceRequest {
account: signer.address(),
denom: denom.clone(),
})
.unwrap()
assert_eq!(request_balance.balance, "900".to_string())
let request_balance = assetft
.query_balance(&QueryBalanceRequest {
account: receiver.address(),
denom: denom.clone(),
})
.unwrap()
assert_eq!(request_balance.balance, "100".to_string());
版本控制
coreum-test-tube的版本由其依赖项、Coreum和test-tube的版本以及其自身更改决定。版本表示为A.B.C格式,其中
- A是Coreum的主版本,
- B是coreum-test-tube的次版本,
- C是coreum-test-tube自身的补丁号。
当Coreum发布新版本并包含破坏性更改时,如果test-tube有任何破坏性更改,我们也将发布破坏性更改,并增加coreum-test-tube的主版本。这样,可以清楚地知道coreum-test-tube的新版本与旧版本不兼容。
当向coreum-test-tube添加向后兼容的新功能时,将增加次要版本号。
当修复错误或进行其他对coreum-test-tube
特定且向后兼容的更改时,将增加补丁号。
请在升级包时查看升级指南,以防出现破坏性更改。
请注意,我们独立于依赖项的版本跟踪包的版本。
依赖项
~24–39MB
~700K SLoC