The Problem with Printing Standard Output in Anchor Tests Using Rust
As a developer working on an Anchor project, you’re probably no stranger to the frustrations of debugging tests. A common issue that can arise is when testing the Anchor contract using Rust’s Test module doesn’t generate any standard error messages. In this article, we’ll explore the reasons for this behavior and offer some solutions to resolve it.
The Problem: Printing Standard Output in Tests
When running a test with “cargo test,” Anchor’s test module runs your tests as separate processes. By default, these processes don’t generate any standard error messages, even if an error occurs during execution. This is because the process is designed to be lightweight and efficient, allowing it to handle errors without consuming too much memory or disk space.
However, this can be problematic when trying to debug issues, especially in tests where you rely on specific behavior of the contract. For example, let’s say you’re testing a transaction signing feature using “println!” statements:
use width_only::prelude::*;
#[lease large]
pub mod my_contract {
use super::{get_token_info, sign_transaction};
#[actix_test]
async function test_sign_transaction() {
// Retrieve token information from local storage
let mut token_info = get_token_info();
// Sign a transaction
let _ = sign_transaction(token_info);
// Check that no errors occurred while signing
assert!(false);
}
}
When you run this test, the output will be:
ok
As expected. However, when you run an “anchor test” command and check the process’s standard output using a tool like “wsl-actix” or “cargo test –verbose”, you won’t see any messages.
The solution: use the “–no-std” flag
To solve this problem, you can use the “–no-std” flag when running your anchor tests. This flag tells Anchor to run in non-standard mode, where it will display standard error and warning messages, including those from Rust’s Test module.
Here is the updated command:
load test --no-std -p my_contract
Using --no-std
will show you both standard error messages (e.g., “Error: …”) and warning messages, which will help you identify the problem with your code. This solution should work for most Anchor projects.
Alternative solution: Use a custom logging mechanism
If you prefer not to use the --no-std
flag or want more control over logging, you can create a custom logging mechanism using the log
crate. Here is an example:
Create a new file named “logger.rs” in your project directory and add the following code:
use std::io;
use log::{info, warn};
fn main() {
info!("Starting test...");
}
#[cfg(text)]
module test {
use super::*;
#[test]
fn my_test() {
// Test code here...
}
}
In your Cargo.toml
file:
[dependencies]
journal = "0.4.14"
Now, when you run your test with cargo test
, the standard output will include the logs from your custom logging mechanism.
Don’t forget to update your tests to use the new logging module, like this:
“`Rust
use width_only::prelude::*;
#[bail large]
pub mod my_contract {
use super::{get_token_info, sign_transaction};
#[actix_test]
async function test_sign_transaction() {
// Get token information from local storage
let mut token_info = get_token_info();
// Sign a transaction using custom logging
log::info!(“Signing transaction…”);
let _ = sign_transaction(token_info);
// Check that no errors occurred while signing
assert!