2
2
3
3
<!-- toc -->
4
4
5
- ** In general, we expect every PR that fixes a bug in rustc to come
6
- accompanied by a regression test of some kind.** This test should fail
7
- in master but pass after the PR. These tests are really useful for
8
- preventing us from repeating the mistakes of the past.
5
+ ** In general, we expect every PR that fixes a bug in rustc to come accompanied
6
+ by a regression test of some kind.** This test should fail in master but pass
7
+ after the PR. These tests are really useful for preventing us from repeating the
8
+ mistakes of the past.
9
9
10
- The first thing to decide is which kind of test to add.
11
- This will depend on the nature of the change and what you want to exercise.
12
- Here are some rough guidelines:
10
+ The first thing to decide is which kind of test to add. This will depend on the
11
+ nature of the change and what you want to exercise. Here are some rough
12
+ guidelines:
13
13
14
14
- The majority of compiler tests are done with [ compiletest] .
15
- - The majority of compiletest tests are [ UI] ( ui.md ) tests in the [ ` tests/ui ` ] directory.
16
- - Changes to the standard library are usually tested within the standard library itself.
17
- - The majority of standard library tests are written as doctests,
18
- which illustrate and exercise typical API behavior.
15
+ - The majority of compiletest tests are [ UI] ( ui.md ) tests in the [ ` tests/ui ` ]
16
+ directory.
17
+ - Changes to the standard library are usually tested within the standard library
18
+ itself.
19
+ - The majority of standard library tests are written as doctests, which
20
+ illustrate and exercise typical API behavior.
19
21
- Additional [ unit tests] ( intro.md#package-tests ) should go in
20
- ` library/${crate}/tests ` (where ` ${crate} ` is usually ` core ` , ` alloc ` , or ` std ` ).
21
- - If the code is part of an isolated system, and you are not testing compiler output,
22
- consider using a [ unit or integration test] ( intro.md#package-tests ) .
23
- - Need to run rustdoc? Prefer a ` rustdoc ` or ` rustdoc-ui ` test.
24
- Occasionally you'll need ` rustdoc-js ` as well.
22
+ ` library/${crate}/tests ` (where ` ${crate} ` is usually ` core ` , ` alloc ` , or
23
+ ` std ` ).
24
+ - If the code is part of an isolated system, and you are not testing compiler
25
+ output, consider using a [ unit or integration test] ( intro.md#package-tests ) .
26
+ - Need to run rustdoc? Prefer a ` rustdoc ` or ` rustdoc-ui ` test. Occasionally
27
+ you'll need ` rustdoc-js ` as well.
25
28
- Other compiletest test suites are generally used for special purposes:
26
29
- Need to run gdb or lldb? Use the ` debuginfo ` test suite.
27
- - Need to inspect LLVM IR or MIR IR? Use the ` codegen ` or ` mir-opt ` test suites.
28
- - Need to inspect the resulting binary in some way?
29
- Then use ` run-make ` .
30
+ - Need to inspect LLVM IR or MIR IR? Use the ` codegen ` or ` mir-opt ` test
31
+ suites.
32
+ - Need to inspect the resulting binary in some way? Or if all the other test
33
+ suites are too limited for your purposes? Then use ` run-make ` .
30
34
- Check out the [ compiletest] chapter for more specialized test suites.
31
35
36
+ After deciding on which kind of test to add, see [ best
37
+ practices] ( best-practices.md ) for guidance on how to author tests that are easy
38
+ to work with that stand the test of time (i.e. if a test fails or need to be
39
+ modified several years later, how can we make it easier for them?).
40
+
32
41
[ compiletest ] : compiletest.md
33
42
[ `tests/ui` ] : https://github.com/rust-lang/rust/tree/master/tests/ui/
34
43
35
44
## UI test walkthrough
36
45
37
- The following is a basic guide for creating a [ UI test] ( ui.md ) , which is one
38
- of the most common compiler tests.
39
- For this tutorial, we'll be adding a test for an async error message.
46
+ The following is a basic guide for creating a [ UI test] ( ui.md ) , which is one of
47
+ the most common compiler tests. For this tutorial, we'll be adding a test for an
48
+ async error message.
40
49
41
- ### Step 1. Add a test file
50
+ ### Step 1: Add a test file
42
51
43
- The first step is to create a Rust source file somewhere in the
44
- [ ` tests/ui ` ] tree.
45
- When creating a test, do your best to find a good location and name (see [ Test
46
- organization] ( ui.md#test-organization ) for more).
47
- Since naming is the hardest part of development, everything should be downhill
48
- from here!
52
+ The first step is to create a Rust source file somewhere in the [ ` tests/ui ` ]
53
+ tree. When creating a test, do your best to find a good location and name (see
54
+ [ Test organization] ( ui.md#test-organization ) for more). Since naming is the
55
+ hardest part of development, everything should be downhill from here!
49
56
50
57
Let's place our async test at ` tests/ui/async-await/await-without-async.rs ` :
51
58
52
59
``` rust,ignore
53
- // Check what happens when using await in a non-async fn .
60
+ // Provide diagnostics when the user writes ` await` in a non-` async` function .
54
61
//@ edition:2018
55
62
56
63
async fn foo() {}
@@ -64,24 +71,22 @@ fn main() {}
64
71
65
72
A few things to notice about our test:
66
73
67
- * The top should start with a short comment that [ explains what the test is
74
+ - The top should start with a short comment that [ explains what the test is
68
75
for] ( #explanatory_comment ) .
69
- * The ` //@ edition:2018 ` comment is called a [ header] ( headers.md ) which provides
70
- instructions to compiletest on how to build the test.
71
- Here we need to set the edition for ` async ` to work (the default is 2015).
72
- * Following that is the source of the test.
73
- Try to keep it succinct and to the point.
74
- This may require some effort if you are trying to minimize an example from a
75
- bug report.
76
- * We end this test with an empty ` fn main ` function.
77
- This is because the default for UI tests is a ` bin ` crate-type,
78
- and we don't want the "main not found" error in our test.
79
- Alternatively, you could add ` #![crate_type="lib"] ` .
80
-
81
- ### Step 2. Generate the expected output
82
-
83
- The next step is to create the expected output from the compiler.
84
- This can be done with the ` --bless ` option:
76
+ - The ` //@ edition:2018 ` comment is called a [ directive] ( directives.md ) which
77
+ provides instructions to compiletest on how to build the test. Here we need to
78
+ set the edition for ` async ` to work (the default is edition 2015).
79
+ - Following that is the source of the test. Try to keep it succinct and to the
80
+ point. This may require some effort if you are trying to minimize an example
81
+ from a bug report.
82
+ - We end this test with an empty ` fn main ` function. This is because the default
83
+ for UI tests is a ` bin ` crate-type, and we don't want the "main not found"
84
+ error in our test. Alternatively, you could add ` #![crate_type="lib"] ` .
85
+
86
+ ### Step 2: Generate the expected output
87
+
88
+ The next step is to create the expected output snapshots from the compiler. This
89
+ can be done with the ` --bless ` option:
85
90
86
91
``` sh
87
92
./x test tests/ui/async-await/await-without-async.rs --bless
@@ -91,28 +96,30 @@ This will build the compiler (if it hasn't already been built), compile the
91
96
test, and place the output of the compiler in a file called
92
97
` tests/ui/async-await/await-without-async.stderr ` .
93
98
94
- However, this step will fail!
95
- You should see an error message, something like this:
99
+ However, this step will fail! You should see an error message, something like
100
+ this:
96
101
97
102
> error: /rust/tests/ui/async-await/await-without-async.rs:7: unexpected
98
103
> error: '7:10: 7:16: ` await ` is only allowed inside ` async ` functions and
99
104
> blocks E0728'
100
105
101
- ### Step 3. Add error annotations
106
+ This is because the stderr contains errors which were not matched by error
107
+ annotations in the source file.
108
+
109
+ ### Step 3: Add error annotations
102
110
103
- Every error needs to be annotated with a comment in the source with the text
104
- of the error.
105
- In this case, we can add the following comment to our test file:
111
+ Every error needs to be annotated with a comment in the source with the text of
112
+ the error. In this case, we can add the following comment to our test file:
106
113
107
114
``` rust,ignore
108
115
fn bar() {
109
116
foo().await
110
- //~^ ERROR `await` is only allowed inside `async` functions and blocks
117
+ //~^ ERROR `await` is only allowed inside `async` functions and blocks
111
118
}
112
119
```
113
120
114
121
The ` //~^ ` squiggle caret comment tells compiletest that the error belongs to
115
- the previous line (more on this in the [ Error
122
+ the * previous* line (more on this in the [ Error
116
123
annotations] ( ui.md#error-annotations ) section).
117
124
118
125
Save that, and run the test again:
@@ -123,16 +130,15 @@ Save that, and run the test again:
123
130
124
131
It should now pass, yay!
125
132
126
- ### Step 4. Review the output
133
+ ### Step 4: Review the output
127
134
128
135
Somewhat hand-in-hand with the previous step, you should inspect the ` .stderr `
129
- file that was created to see if it looks like how you expect.
130
- If you are adding a new diagnostic message, now would be a good time to
131
- also consider how readable the message looks overall, particularly for
132
- people new to Rust.
136
+ file that was created to see if it looks like how you expect. If you are adding
137
+ a new diagnostic message, now would be a good time to also consider how readable
138
+ the message looks overall, particularly for people new to Rust.
133
139
134
- Our example ` tests/ui/async-await/await-without-async.stderr ` file should
135
- look like this:
140
+ Our example ` tests/ui/async-await/await-without-async.stderr ` file should look
141
+ like this:
136
142
137
143
``` text
138
144
error[E0728]: `await` is only allowed inside `async` functions and blocks
@@ -148,48 +154,47 @@ error: aborting due to previous error
148
154
For more information about this error, try `rustc --explain E0728`.
149
155
```
150
156
151
- You may notice some things look a little different than the regular
152
- compiler output.
153
- The ` $DIR ` removes the path information which will differ between systems.
154
- The ` LL ` values replace the line numbers.
155
- That helps avoid small changes in the source from triggering large diffs.
156
- See the [ Normalization] ( ui.md#normalization ) section for more.
157
+ You may notice some things look a little different than the regular compiler
158
+ output.
159
+
160
+ - The ` $DIR ` removes the path information which will differ between systems.
161
+ - The ` LL ` values replace the line numbers. That helps avoid small changes in
162
+ the source from triggering large diffs. See the
163
+ [ Normalization] ( ui.md#normalization ) section for more.
157
164
158
165
Around this stage, you may need to iterate over the last few steps a few times
159
166
to tweak your test, re-bless the test, and re-review the output.
160
167
161
- ### Step 5. Check other tests
168
+ ### Step 5: Check other tests
162
169
163
- Sometimes when adding or changing a diagnostic message, this will affect
164
- other tests in the test suite.
165
- The final step before posting a PR is to check if you have affected anything else.
166
- Running the UI suite is usually a good start:
170
+ Sometimes when adding or changing a diagnostic message, this will affect other
171
+ tests in the test suite. The final step before posting a PR is to check if you
172
+ have affected anything else. Running the UI suite is usually a good start:
167
173
168
174
``` sh
169
175
./x test tests/ui
170
176
```
171
177
172
- If other tests start failing, you may need to investigate what has changed
173
- and if the new output makes sense.
178
+ If other tests start failing, you may need to investigate what has changed and
179
+ if the new output makes sense.
180
+
174
181
You may also need to re-bless the output with the ` --bless ` flag.
175
182
176
183
<a name =" explanatory_comment " ></a >
177
184
178
185
## Comment explaining what the test is about
179
186
180
- The first comment of a test file should ** summarize the point
181
- of the test** , and highlight what is important about it.
182
- If there is an issue number associated with the test, include
183
- the issue number.
184
-
185
- This comment doesn't have to be super extensive. Just something like
186
- "Regression test for #18060 : match arms were matching in the wrong
187
- order." might already be enough.
188
-
189
- These comments are very useful to others later on when your test
190
- breaks, since they often can highlight what the problem is. They are
191
- also useful if for some reason the tests need to be refactored, since
192
- they let others know which parts of the test were important (often a
193
- test must be rewritten because it no longer tests what is was meant to
194
- test, and then it's useful to know what it * was* meant to test
195
- exactly).
187
+ The first comment of a test file should ** summarize the point of the test** , and
188
+ highlight what is important about it. If there is an issue number associated
189
+ with the test, include the issue number.
190
+
191
+ This comment doesn't have to be super extensive. Just something like "Regression
192
+ test for #18060 : match arms were matching in the wrong order." might already be
193
+ enough.
194
+
195
+ These comments are very useful to others later on when your test breaks, since
196
+ they often can highlight what the problem is. They are also useful if for some
197
+ reason the tests need to be refactored, since they let others know which parts
198
+ of the test were important. Often a test must be rewritten because it no longer
199
+ tests what is was meant to test, and then it's useful to know what it * was*
200
+ meant to test exactly.
0 commit comments