1 unstable release

0.2.0 Jul 7, 2021
0.1.0 Jun 1, 2021

#202 in Testing

MIT/Apache

21KB
380 lines

caplog

A Rust library providing log capture facilities for testing.

This crate is primarily intended for use with the log crate, however additional logging facilities are welcome.

Usage

use log::warn;

#[test]
fn test_scramble_message() {
   let handle = caplog::get_handle();
   warn!("scrambled eggs");
   assert!(handle.any_msg_contains("scrambled eggs"));
}

lib.rs:

Utility for capturing and verification of log messages. Intended for use in testing of applications and libraries.

Inspired by the fixture of the same name from pytest.

Using Caplog

The primary functions of interest are get_handle and CaplogHandle::iter. Use get_handle at the top of your test in order to get a view of the messages being logged. After this, call .iter on the handle at any point in your test to get an Iterator<Record>. This iterator can then be used to view log messages.

# use log::{info, warn};
use caplog::get_handle;

let handle = caplog::get_handle();
warn!("terrible thing happened!");
assert!(handle.iter().any(|rec| rec.msg.contains("terrible")));

Handle's view of logs

Each handle has access to all messages sent while it was alive. This means that messages sent before it is made will not be available via iter or any other functions on it. So it is recommended to call get_handle at the top of tests to ensure the messages will be scope.

Threading concerns

As the log interface is global, messages from other threads may be visible via the handle. Due to this, it is recommended to check for messages unique to the test when possible. For example:

# use log::{info, warn};
# use caplog::get_handle;

fn handle_request(id: u32) -> Result<(), ()> {
   info!("Got request from client {}", id);
   Ok(())
}

let handle = caplog::get_handle();
let client_id = 12345; // id unique to this test
handle_request(client_id).unwrap();
handle.any_msg_contains(&format!("Got request from client {}", client_id));

Due to info! and the other log macros being blocking, it can be guaranteed that a message will be visible to the same thread it was called on by the time it returns.

Interaction with other log handlers

log's interface only allows for a single log handler at a time. In order to prevent collision with the regular handler, it is recommended to put initialization code for it either inside of main or put a [cfg(not(test))] attribute on it.

Dependencies

~91KB