time_test/
lib.rs

1//! `time_test` is a super simple crate that you can use to easily obtain how long
2//! your tests took to run. Using it is simple (see `example/` for an example use
3//! case):
4//!
5//! ```
6//! #[macro_use] extern crate time_test;
7//!
8//! #[cfg(test)]
9//! mod tests {
10//!     #[test]
11//!     fn my_test() {
12//!         time_test!();
13//!
14//!         println!("hello world");
15//!
16//!         {
17//!             time_test!("sub-assert 1");
18//!             assert!(true);
19//!         }
20//!         assert_eq!(1, 1);
21//!     }
22//! }
23//! ```
24//!
25//! Adding the `time_test!()` macro to the line in your test from which you want to
26//! measure the test duration will result in the duration that the test has taken
27//! being shown in the test result line:
28//!
29//! ```bash
30//! $ # 1 test thread so that the output is not garbled.
31//! $ cargo test -- --test-threads=1
32//!
33//!     Finished dev [unoptimized + debuginfo] target(s) in 0.78 secs
34//!      Running target/debug/deps/example-a84426a5de188514
35//!
36//! running 1 test
37//! test example::tests::my_test ... (sub-assert 1 took PT0.000002421S) (took PT0.000004178S) ok
38//! ```
39
40use std::io::{self, Write};
41
42use std::time::Instant;
43
44/// TestTimer allows to easily time tests. It's recommended to use the time_test!() macro instead
45/// of invoking this type directly.
46pub struct TestTimer(Instant, String);
47
48impl TestTimer {
49    pub fn new(desc: String) -> TestTimer {
50        TestTimer(Instant::now(), desc)
51    }
52}
53
54impl Drop for TestTimer {
55    fn drop(&mut self) {
56        let dur = Instant::now()
57            .checked_duration_since(self.0)
58            .unwrap_or_default();
59        let millis = (dur.as_nanos() as f64) / 1_000_000.0;
60        if self.1.is_empty() {
61            write!(io::stderr(), "(took {} ms) ", millis).unwrap_or(());
62        } else {
63            write!(io::stderr(), "({} took {} ms) ", self.1, millis).unwrap_or(());
64        }
65    }
66}
67
68#[macro_export]
69macro_rules! time_test {
70    () => {
71        use time_test::TestTimer;
72        let _tt = TestTimer::new(String::new());
73    };
74    ($desc:expr) => {
75        use time_test::TestTimer;
76        let _tt = TestTimer::new($desc.to_string());
77    };
78}
79
80#[cfg(test)]
81mod tests {
82    use crate as time_test;
83    #[test]
84    fn test_time_test() {
85        time_test!();
86        assert!(true);
87    }
88}