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