Writing test and doc at once in Rust

Rust language allows inline documentation by writing triple slash comments (markdown syntax) just above the function signature and, of course, also unit testing.

See this introduction example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/// Returns how many **non-dot chars** are in a string.
pub fn non_dot_chars(s: &str) -> usize {                                                                        
    s.chars().filter(|&c| c != '.').count()                                                                     
}                                                                                                               
                                                                                                                
#[cfg(test)]                                                                                                    
mod tests {                                                                                                     
    use super::*;                                                                                               
                                                                                                                
    #[test]                                                                                                     
    fn test_non_dot_chars() {                                                                                   
        assert!(0 == non_dot_chars(""));                                                                        
        assert!(0 == non_dot_chars("."));                                                                       
        assert!(1 == non_dot_chars("a"));                                                                       
        assert!(2 == non_dot_chars(".ab..."));                                                                  
    }                                                                                                           
}

Tests within the function documentation

But in Rust, it is possible to mix both concepts: tests within the function documentation in a code block (triple backticks, markdown syntax) and including the test assertions inside:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/// Returns how many *non-dot chars* are in a string.
/// ```
/// assert!(0 == utils::non_dot_chars(""));
/// assert!(0 == utils::non_dot_chars("."));
/// assert!(1 == utils::non_dot_chars("a"));
/// assert!(3 == utils::non_dot_chars(".a...bc.."));
/// ```
pub fn non_dot_chars(s: &str) -> usize {                                                                        
    s.chars().filter(|&c| c != '.').count()                                                                     
}                                                                                                               

Note that a crate namespace (utils:: in this example) must be used to set the crate location for the function (it is usually your project name).

Execute the tests

Now, cargo test will scan and execute the Doc-tests:

/2022/05/15/writing-test-and-doc-at-once-in-rust/cargo_test.png

Generate documentation

To generate the documentation, you use the cargo doc command. It will create the documentation under the subdirectory target/doc/utils:

/2022/05/15/writing-test-and-doc-at-once-in-rust/cargo_doc.png

You have probably observed many examples in The Rust Standard Library documentation that include test assertions. Now, you can imaging the reason why they are there.

See also