1# Documentation tests 2 3`rustdoc` supports executing your documentation examples as tests. This makes sure 4that examples within your documentation are up to date and working. 5 6The basic idea is this: 7 8```rust,no_run 9/// # Examples 10/// 11/// ``` 12/// let x = 5; 13/// ``` 14# fn f() {} 15``` 16 17The triple backticks start and end code blocks. If this were in a file named `foo.rs`, 18running `rustdoc --test foo.rs` will extract this example, and then run it as a test. 19 20Please note that by default, if no language is set for the block code, rustdoc 21assumes it is Rust code. So the following: 22 23``````markdown 24```rust 25let x = 5; 26``` 27`````` 28 29is strictly equivalent to: 30 31``````markdown 32``` 33let x = 5; 34``` 35`````` 36 37There's some subtlety though! Read on for more details. 38 39## Passing or failing a doctest 40 41Like regular unit tests, regular doctests are considered to "pass" 42if they compile and run without panicking. 43So if you want to demonstrate that some computation gives a certain result, 44the `assert!` family of macros works the same as other Rust code: 45 46```rust 47let foo = "foo"; 48assert_eq!(foo, "foo"); 49``` 50 51This way, if the computation ever returns something different, 52the code panics and the doctest fails. 53 54## Pre-processing examples 55 56In the example above, you'll note something strange: there's no `main` 57function! Forcing you to write `main` for every example, no matter how small, 58adds friction and clutters the output. So `rustdoc` processes your examples 59slightly before running them. Here's the full algorithm `rustdoc` uses to 60preprocess examples: 61 621. Some common `allow` attributes are inserted, including 63 `unused_variables`, `unused_assignments`, `unused_mut`, 64 `unused_attributes`, and `dead_code`. Small examples often trigger 65 these lints. 662. Any attributes specified with `#![doc(test(attr(...)))]` are added. 673. Any leading `#![foo]` attributes are left intact as crate attributes. 684. If the example does not contain `extern crate`, and 69 `#![doc(test(no_crate_inject))]` was not specified, then `extern crate 70 <mycrate>;` is inserted (note the lack of `#[macro_use]`). 715. Finally, if the example does not contain `fn main`, the remainder of the 72 text is wrapped in `fn main() { your_code }`. 73 74For more about that caveat in rule 4, see "Documenting Macros" below. 75 76## Hiding portions of the example 77 78Sometimes, you need some setup code, or other things that would distract 79from your example, but are important to make the tests work. Consider 80an example block that looks like this: 81 82```rust,no_run 83/// ``` 84/// /// Some documentation. 85/// # fn foo() {} // this function will be hidden 86/// println!("Hello, World!"); 87/// ``` 88# fn f() {} 89``` 90 91It will render like this: 92 93```rust 94/// Some documentation. 95# fn foo() {} 96println!("Hello, World!"); 97``` 98 99Yes, that's right: you can add lines that start with `# `, and they will 100be hidden from the output, but will be used when compiling your code. You 101can use this to your advantage. In this case, documentation comments need 102to apply to some kind of function, so if I want to show you just a 103documentation comment, I need to add a little function definition below 104it. At the same time, it's only there to satisfy the compiler, so hiding 105it makes the example more clear. You can use this technique to explain 106longer examples in detail, while still preserving the testability of your 107documentation. 108 109For example, imagine that we wanted to document this code: 110 111```rust 112let x = 5; 113let y = 6; 114println!("{}", x + y); 115``` 116 117We might want the documentation to end up looking like this: 118 119> First, we set `x` to five: 120> 121> ```rust 122> let x = 5; 123> # let y = 6; 124> # println!("{}", x + y); 125> ``` 126> 127> Next, we set `y` to six: 128> 129> ```rust 130> # let x = 5; 131> let y = 6; 132> # println!("{}", x + y); 133> ``` 134> 135> Finally, we print the sum of `x` and `y`: 136> 137> ```rust 138> # let x = 5; 139> # let y = 6; 140> println!("{}", x + y); 141> ``` 142 143To keep each code block testable, we want the whole program in each block, but 144we don't want the reader to see every line every time. Here's what we put in 145our source code: 146 147``````markdown 148First, we set `x` to five: 149 150``` 151let x = 5; 152# let y = 6; 153# println!("{}", x + y); 154``` 155 156Next, we set `y` to six: 157 158``` 159# let x = 5; 160let y = 6; 161# println!("{}", x + y); 162``` 163 164Finally, we print the sum of `x` and `y`: 165 166``` 167# let x = 5; 168# let y = 6; 169println!("{}", x + y); 170``` 171`````` 172 173By repeating all parts of the example, you can ensure that your example still 174compiles, while only showing the parts that are relevant to that part of your 175explanation. 176 177The `#`-hiding of lines can be prevented by using two consecutive hashes 178`##`. This only needs to be done with the first `#` which would've 179otherwise caused hiding. If we have a string literal like the following, 180which has a line that starts with a `#`: 181 182```rust 183let s = "foo 184## bar # baz"; 185``` 186 187We can document it by escaping the initial `#`: 188 189```text 190/// let s = "foo 191/// ## bar # baz"; 192``` 193 194 195## Using `?` in doc tests 196 197When writing an example, it is rarely useful to include a complete error 198handling, as it would add significant amounts of boilerplate code. Instead, you 199may want the following: 200 201```rust,no_run 202/// ``` 203/// use std::io; 204/// let mut input = String::new(); 205/// io::stdin().read_line(&mut input)?; 206/// ``` 207# fn f() {} 208``` 209 210The problem is that `?` returns a `Result<T, E>` and test functions don't 211return anything, so this will give a mismatched types error. 212 213You can get around this limitation by manually adding a `main` that returns 214`Result<T, E>`, because `Result<T, E>` implements the `Termination` trait: 215 216```rust,no_run 217/// A doc test using ? 218/// 219/// ``` 220/// use std::io; 221/// 222/// fn main() -> io::Result<()> { 223/// let mut input = String::new(); 224/// io::stdin().read_line(&mut input)?; 225/// Ok(()) 226/// } 227/// ``` 228# fn f() {} 229``` 230 231Together with the `# ` from the section above, you arrive at a solution that 232appears to the reader as the initial idea but works with doc tests: 233 234```rust,no_run 235/// ``` 236/// use std::io; 237/// # fn main() -> io::Result<()> { 238/// let mut input = String::new(); 239/// io::stdin().read_line(&mut input)?; 240/// # Ok(()) 241/// # } 242/// ``` 243# fn f() {} 244``` 245 246As of version 1.34.0, one can also omit the `fn main()`, but you will have to 247disambiguate the error type: 248 249```rust,no_run 250/// ``` 251/// use std::io; 252/// let mut input = String::new(); 253/// io::stdin().read_line(&mut input)?; 254/// # Ok::<(), io::Error>(()) 255/// ``` 256# fn f() {} 257``` 258 259This is an unfortunate consequence of the `?` operator adding an implicit 260conversion, so type inference fails because the type is not unique. Please note 261that you must write the `(())` in one sequence without intermediate whitespace 262so that `rustdoc` understands you want an implicit `Result`-returning function. 263 264## Showing warnings in doctests 265 266You can show warnings in doctests by running `rustdoc --test --test-args=--show-output` 267(or, if you're using cargo, `cargo test --doc -- --show-output`). 268By default, this will still hide `unused` warnings, since so many examples use private functions; 269you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings. 270You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally. 271 272[test-attr]: ./the-doc-attribute.md#testattr 273 274## Documenting macros 275 276Here’s an example of documenting a macro: 277 278```rust 279/// Panic with a given message unless an expression evaluates to true. 280/// 281/// # Examples 282/// 283/// ``` 284/// # #[macro_use] extern crate foo; 285/// # fn main() { 286/// panic_unless!(1 + 1 == 2, “Math is broken.”); 287/// # } 288/// ``` 289/// 290/// ```should_panic 291/// # #[macro_use] extern crate foo; 292/// # fn main() { 293/// panic_unless!(true == false, “I’m broken.”); 294/// # } 295/// ``` 296#[macro_export] 297macro_rules! panic_unless { 298 ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } }); 299} 300# fn main() {} 301``` 302 303You’ll note three things: we need to add our own `extern crate` line, so that 304we can add the `#[macro_use]` attribute. Second, we’ll need to add our own 305`main()` as well (for reasons discussed above). Finally, a judicious use of 306`#` to comment out those two things, so they don’t show up in the output. 307 308## Attributes 309 310Code blocks can be annotated with attributes that help `rustdoc` do the right 311thing when testing your code: 312 313The `ignore` attribute tells Rust to ignore your code. This is almost never 314what you want as it's the most generic. Instead, consider annotating it 315with `text` if it's not code or using `#`s to get a working example that 316only shows the part you care about. 317 318```rust 319/// ```ignore 320/// fn foo() { 321/// ``` 322# fn foo() {} 323``` 324 325`should_panic` tells `rustdoc` that the code should compile correctly but 326panic during execution. If the code doesn't panic, the test will fail. 327 328```rust 329/// ```should_panic 330/// assert!(false); 331/// ``` 332# fn foo() {} 333``` 334 335The `no_run` attribute will compile your code but not run it. This is 336important for examples such as "Here's how to retrieve a web page," 337which you would want to ensure compiles, but might be run in a test 338environment that has no network access. 339 340```rust 341/// ```no_run 342/// loop { 343/// println!("Hello, world"); 344/// } 345/// ``` 346# fn foo() {} 347``` 348 349`compile_fail` tells `rustdoc` that the compilation should fail. If it 350compiles, then the test will fail. However, please note that code failing 351with the current Rust release may work in a future release, as new features 352are added. 353 354```rust 355/// ```compile_fail 356/// let x = 5; 357/// x += 2; // shouldn't compile! 358/// ``` 359# fn foo() {} 360``` 361 362`edition2018` tells `rustdoc` that the code sample should be compiled using 363the 2018 edition of Rust. Similarly, you can specify `edition2015` to compile 364the code with the 2015 edition. 365 366```rust 367/// Only runs on the 2018 edition. 368/// 369/// ```edition2018 370/// let result: Result<i32, ParseIntError> = try { 371/// "1".parse::<i32>()? 372/// + "2".parse::<i32>()? 373/// + "3".parse::<i32>()? 374/// }; 375/// ``` 376# fn foo() {} 377``` 378 379## Syntax reference 380 381The *exact* syntax for code blocks, including the edge cases, can be found 382in the [Fenced Code Blocks](https://spec.commonmark.org/0.29/#fenced-code-blocks) 383section of the CommonMark specification. 384 385Rustdoc also accepts *indented* code blocks as an alternative to fenced 386code blocks: instead of surrounding your code with three backticks, you 387can indent each line by four or more spaces. 388 389``````markdown 390 let foo = "foo"; 391 assert_eq!(foo, "foo"); 392`````` 393 394These, too, are documented in the CommonMark specification, in the 395[Indented Code Blocks](https://spec.commonmark.org/0.29/#indented-code-blocks) 396section. 397 398However, it's preferable to use fenced code blocks over indented code blocks. 399Not only are fenced code blocks considered more idiomatic for Rust code, 400but there is no way to use attributes such as `ignore` or `should_panic` with 401indented code blocks. 402 403### Include items only when collecting doctests 404 405Rustdoc's documentation tests can do some things that regular unit tests can't, so it can 406sometimes be useful to extend your doctests with samples that wouldn't otherwise need to be in 407documentation. To this end, Rustdoc allows you to have certain items only appear when it's 408collecting doctests, so you can utilize doctest functionality without forcing the test to appear in 409docs, or to find an arbitrary private item to include it on. 410 411When compiling a crate for use in doctests (with `--test` option), `rustdoc` will set `#[cfg(doctest)]`. 412Note that they will still link against only the public items of your crate; if you need to test 413private items, you need to write a unit test. 414 415In this example, we're adding doctests that we know won't compile, to verify that our struct can 416only take in valid data: 417 418```rust 419/// We have a struct here. Remember it doesn't accept negative numbers! 420pub struct MyStruct(pub usize); 421 422/// ```compile_fail 423/// let x = my_crate::MyStruct(-5); 424/// ``` 425#[cfg(doctest)] 426pub struct MyStructOnlyTakesUsize; 427``` 428 429Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate 430API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while `rustdoc` is 431collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc, 432but is hidden from the public documentation. 433 434Another possible use of `#[cfg(doctest)]` is to test doctests that are included in your README file 435without including it in your main documentation. For example, you could write this into your 436`lib.rs` to test your README as part of your doctests: 437 438```rust,no_run 439#[doc = include_str!("../README.md")] 440#[cfg(doctest)] 441pub struct ReadmeDoctests; 442``` 443 444This will include your README as documentation on the hidden struct `ReadmeDoctests`, which will 445then be tested alongside the rest of your doctests. 446