I am writing integration tests for a library and I want to test if in a certain scenario a particular trace line was emitted. I see how tracing-test can capture a trace within a test step, I had a look at tracing-fluent-assertions and test-log, but all of these seem to do almost what I need, just not exactly that.
In my case I have one test step which causes some trace lines to be emitted, and I need to check in another test step that these trace lines were actually emitted. Do you know of a way to do this? I'd thought that tracing-subscriber or cucumber already have means to do this, but I don't see it in their documentation.
This is a the structure of a minimal example:
.
│ Cargo.toml
├───src
│ │ lib.rs
│ └───bin
│ test-of-trace.rs
└───tests
│ minimal.rs
└───features
minimal.feature
The library defines one function which we will call in our integration test. We use the tracing crate for generating traces.
// lib.rs
use tracing::{info, trace};
pub fn add(left: usize, right: usize) -> usize {
trace!("I'm adding");
let result = left + right;
info!("The result is {}", result);
result
}
The integration test is done with cucumber-rs. This is our feature file defining our test:
# tests/features/minimal.feature
Feature: Test if trace was emitted
Scenario: Emit and check trace
When I call the add function
Then a trace is emitted
We implement the test steps with cucumber-rs as follows:
// tests/minimal.rs
use cucumber::{then, when, World};
use test_of_trace;
#[derive(Debug, World)]
#[world(init = Self::new)]
pub struct TestWorld {}
impl TestWorld {
fn new() -> Self {
Self {}
}
}
#[when("I call the add function")]
fn call_add(_world: &mut TestWorld) {
test_of_trace::add(3, 4);
}
#[then("a trace is emitted")]
fn trace_is_emitted(_world: &mut TestWorld) {
//TODO
assert!(false); // how to look up if the trace was emitted?
}
#[tokio::main]
async fn main() {
TestWorld::run("tests/features").await;
}
We tell cargo
about our integration test in the table [[test]]
[package]
name = "test-of-trace"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tracing = "0.1.37"
tracing-subscriber = {version = "0.3.16", features = ["env-filter", "registry"]}
[dev-dependencies]
cucumber = "0.19"
futures = "0.3"
tokio = { version = "1.25", features = ["macros", "rt-multi-thread", "time"] }
[[test]]
name = "minimal"
harness = false
Additionaly we can create a binary which will run and show that the traces are actually emitted when the add function runs
// bin/test-of-trace.rs
use test_of_trace;
use tracing::{instrument, trace};
use tracing_subscriber::{fmt, EnvFilter};
fn install_tracing() {
fmt()
.without_time()
.with_line_number(true)
.with_env_filter(
EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("trace"))
.unwrap(),
)
.init();
}
#[instrument]
fn main() {
install_tracing();
trace!("Starting {}", env!("CARGO_PKG_NAME"));
test_of_trace::add(5, 8);
trace!("Finishing {}", env!("CARGO_PKG_NAME"));
}
This example is also available as a repository