Osmosis Test Tube
Osmosis Test Tube is a rust-based test framework that allows developers to test for multi-contract interactions without having to dispatch messages, storage and other variables themselves. This environment is even closer to the actual on-chain mechanisms than Cw Multi Test, because it runs tests directly on the actual chain binaries. With cw-orchestrator, most of the osmosis-test-tube
logic is abstracted away, but you can still learn more about the framework here.
Prerequesites
In order to use osmosis-test-tube
, the library needs to be able to compile and install the chain binaries. For that you will need to install a go compiler as well as the clang library. Run the following commands to install both of those libraries.
Ubuntu
- Install go
- Install the clang library
sudo apt install clang
Arch Linux
- Install go
sudo pacman -Sy go
- Install the clang library
sudo pacman -Sy clang
Quick Start
Before starting, here is a few examples utilizing the osmosis-test-tube environment
To be able to use osmosis-test-tuee
you need to add the cw-orch-osmosis-test-tube
dependency inside your crate.
Creating a test environment in cw-orchestrator that leverages osmosis-test-tube
goes along the lines of:
use cw_orch::prelude::*;
use cw_orch_osmosis_test_tube::OsmosisTestTube;
use cosmwasm_std::coins;
let mut chain = OsmosisTestTube::new(coins(1_000_000_000_000, "uosmo"));
This snippet will create a new address, provide it with initial balances and create the osmosis-test-tube
environment.
The addresses are not handled like in the cw-multi-test
environment or in mock tests and can’t be decided upon manually. You will learn more later about handling addresses in the OsmosisTestTube environment.
NOTE: When using
osmosis-test-tube
, the addresses are validated like on a live chain.
NOTE: When using
osmosis-test-tube
, gas fees are charged to the sender address. The gas fees don’t represent the actual gas fees you will occur when interacting with the actual chain. That’s why in the test snippet above, the amount ofuosmo
instantiated with the account is very high.
Interacting with contracts
You can then use the resulting OsmosisTestTube
variable to interact with your contracts:
let contract_counter = CounterContract::new(chain.clone());
let upload_res = contract_counter.upload();
assert!(upload_res.is_ok());
let init_res = contract_counter.instantiate(&InstantiateMsg { count: 0 }, None, None);
assert!(init_res.is_ok());
When executing contracts in an osmosis_test_tube
environment, the messages and sub-messages sent along the Response of an endpoint, will be executed as well. This environment mimics the actual on-chain execution by dispatching the messages inside the actual chain binaries.
This environment uses wasm files compiled from the project. Therefore, you need to compile the WASM artifacts from the project for your osmosis-test-tube integration tests. You will need to have the
wasm
function from theUploadable
trait implemented . See the dedicated page for more details.
Cloning
When cloning an osmosis_test_tube
environment, you are not cloning the entire environment, but instead you are creating a new OsmosisTestTube
typed variable with the same underlying osmosis_test_tube::App
object reference. This is useful for objects that require to pass the chain as an object rather than by reference.
The underlying osmosis_test_tube::App
object is however not clonable.
Additional tools
The OsmosisTestTube
test environment allows you to change application variables (such as the balance of an account) using wrappers around the underlying osmosis_test_tube::App
object. Here are some examples of those wrappers in context:
let new_sender = chain.init_account(coins(100_000, "ujunox")).unwrap();
// Reuploads as the new sender
contract_counter.call_as(&new_sender).upload().unwrap();
// Here the contract_counter sender is again `sender`
// Sets the new_sender as the definite sender
contract_counter.set_sender(&new_sender);
// From now on the contract_counter sender is `new_sender`
NOTE: With OsmosisTestTube, you can’t create accounts with a specific address. Accounts are created by the app directly and you don’t have a lot of control over them. As in the example above, use
OsmosisTestTube::init_account
to create a new account.
Additional customization
As we don’t provide wrappers around each and every functionality that osmosis_test_tube
provides, you can also customize the underlying osmosis_test_tube::App
object to your specific needs. In the following example, we increase the block time in the test environment:
chain.app.borrow_mut().increase_time(150);