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