You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Text output that includes many characters like quotes and newlines that require special handling in a string.
25
25
26
-
- Output that is large, making it painful to define the reference output, and bloating the size of the test file and making it hard to navigate.
26
+
- Output that is large, making it painful to define the reference output and bloating the size of the test file.
27
27
28
-
- Binary formats like plots or images, which are very difficult to describe in code: i.e. the plot looks right, the error message is useful to a human, the print method uses colour effectively.
28
+
- Binary formats like plots or images, which are very difficult to describe in code: e.g. the plot looks right, the error message is actionable, or the print method uses colour effectively.
29
29
30
30
For these situations, testthat provides an alternative mechanism: snapshot tests.
31
31
Instead of using code to describe expected output, snapshot tests (also known as [golden tests](https://ro-che.info/articles/2017-12-04-golden-tests)) record results in a separate human readable file.
@@ -103,8 +103,9 @@ test_that("bullets", {
103
103
})
104
104
```
105
105
106
-
```{r, include = FALSE}
107
-
# Reset snapshot test
106
+
```{r}
107
+
#| include: false
108
+
# finalise snapshot to in order to get an error
108
109
snapper$end_file()
109
110
snapper$start_file("snapshotting.Rmd", "test")
110
111
```
@@ -161,38 +162,14 @@ Within a test, each snapshot expectation is indented by four spaces, i.e. as cod
161
162
Because the snapshot output uses the name of the current test file and the current test, snapshot expectations don't really work when run interactively at the console.
162
163
Since they can't automatically find the reference output, they instead just print the current value for manual inspection.
163
164
164
-
## Other types of output
165
-
166
-
### Messages and warnings
165
+
## Testing errors
167
166
168
167
So far we've focussed on snapshot tests for output printed to the console.
169
168
But `expect_snapshot()` also captures messages, errors, and warnings[^1].
170
-
The following function generates a some output, a message, and a warning:
171
-
172
-
[^1]: We no longer recommend `expect_snapshot_output()`, `expect_snapshot_warning()`, or `expect_snapshot_error()`.
173
-
Just use `expect_snapshot()`.
169
+
Messages and warnings are straightforward, but capturing errors is *slightly* more difficult because `expect_snapshot()` will fail if there's an error:
174
170
175
171
```{r}
176
-
f <- function() {
177
-
print("Hello")
178
-
message("Hi!")
179
-
warning("How are you?")
180
-
}
181
-
```
182
-
183
-
And `expect_snapshot()` captures them all:
184
-
185
-
```{r}
186
-
test_that("f() makes lots of noise", {
187
-
expect_snapshot(f())
188
-
})
189
-
```
190
-
191
-
### Errors
192
-
193
-
Capturing errors is *slightly* more difficult because `expect_snapshot()` will fail when there's an error:
194
-
195
-
```{r, error = TRUE}
172
+
#| error: true
196
173
test_that("you can't add a number and a letter", {
Just be careful: when you set `error = TRUE`, `expect_snapshot()` checks that at least one expression throws an error, not that every expression throws an error. For example, look above and notice that adding a date and factor generated a warning, not an error.
200
+
201
+
Snapshot tests are particularly important when testing complex error messages, such as those that you might generate with cli. Here's a more realistic example illustrating how you might test `check_unnamed()`, a function that ensures all arguments in `...` are unnnamed.
test_that("actionable feedback if some or all arguments named", {
227
+
expect_snapshot(error = TRUE, {
228
+
check_unnamed(x = 1, 2)
229
+
check_unnamed(x = 1, y = 2)
218
230
})
219
231
})
220
232
```
221
233
234
+
## Other challenges
235
+
236
+
### Varying outputs
237
+
238
+
Sometimes part of the output varies in ways that you can't easily control. In many cases, it's convenient to use mocking (`vignette("mocking")`) to ensure that every run of the function always produces the same output. In other cases, it's easier to manipulate the text output with a regular expression or similar. That's the job of the `transform` argument which should be passed a function that takes a character vector of lines, and returns a modified vector.
222
239
223
-
Snapshot tests are particularly important when testing complex error messages.
240
+
This type of problem often crops up when you are testing a function that gives feedback about a path. In your tests, you'll typically use a temporary path (e.g. from `withr::local_tempfile()`) so if you display the path in a snapshot, it will be different every time. For example, consider this "safe" version of `writeLines()` that requires to explicitly opt-in to overwriting an existing file:
When generating sophisticated error messages that use cli's interpolation and formatting features, snapshot tests are essential for ensuring the messages render correctly with proper styling and content.
Now even though the path varies, the snapshot does not.
248
304
249
305
### `local_reproducible_output()`
250
306
@@ -254,7 +310,7 @@ By default, testthat sets a number of options that simplify and standardise outp
254
310
* Crayon/cli ANSI colouring and hyperlinks are suppressed.
255
311
* Unicode characters are suppressed.
256
312
257
-
These are sound defaults that we have found useful to minimise spurious diffs between tests run in different environment. But it's sometimes necessary to override them in order to test various output features. So, if necessary, you can override these settings by calling`local_reproducible_output()`.
313
+
These are sound defaults that we have found useful to minimise spurious difference between tests run in different environments. However, there are times when you want to deliberately test different widths, or ANSI escapes, or unicode characters, so you can override the defaults with`local_reproducible_output()`.
258
314
259
315
### Snapshotting graphics
260
316
@@ -273,12 +329,6 @@ test_that("can snapshot a simple list", {
273
329
})
274
330
```
275
331
276
-
## Varying outputs
277
-
278
-
Sometimes part of the output varies in ways that you can't easily control.
279
-
280
-
There are two techniques you can use: mocking or the `transform` output.
281
-
282
332
## Whole file snapshotting
283
333
284
334
`expect_snapshot()`, `expect_snapshot_output()`, `expect_snapshot_error()`, and `expect_snapshot_value()` use one snapshot file per test file.
@@ -313,10 +363,11 @@ The display varies based on the file type (currently text files, common image fi
313
363
314
364
Sometimes the failure occurs in a non-interactive environment where you can't run `snapshot_review()`, e.g. in `R CMD check`.
315
365
In this case, the easiest fix is to retrieve the `.new` file, copy it into the appropriate directory, then run `snapshot_review()` locally.
316
-
If your code was run on a CI platform, you'll need to start by downloading the run "artifact", which contains the check folder.
366
+
If this happens on GitHub, testthat provides some tools to help you in the form of `gh_download_artifact()`.
317
367
318
368
In most cases, we don't expect you to use `expect_snapshot_file()` directly.
319
369
Instead, you'll use it via a wrapper that does its best to gracefully skip tests when differences in platform or package versions make it unlikely to generate perfectly reproducible output.
370
+
That wrapper should also typically call `announce_snapshot_file()` to avoid snapshots being incorrectly cleaned up; see the documentation for more details.
0 commit comments