testthat icon indicating copy to clipboard operation
testthat copied to clipboard

expect_error and friends report unused arguments for `fixed` when used interactively but not when used non-interactively

Open billdenney opened this issue 1 year ago • 3 comments

When I ran the code below interactively, I got the following warning:

Error: 1 did not throw the expected warning.
Warning in expect_warning(1, regexp = "foo", fixed = TRUE) :
  Arguments in `...` must be used.
✖ Problematic argument:
• fixed = TRUE
ℹ Did you misspell an argument name?

But when run in reprex, I don't see the warning about fixed. Why is there different behavior for interactive vs non-interactive use for argument matching?

library(testthat)

expect_message(
  message("foo"),
  regexp = "foo",
  fixed = TRUE
)
  
expect_message(
  1,
  regexp = "foo",
  fixed = TRUE
)
#> Error: 1 did not produce any messages.

expect_warning(
  warning("foo"),
  regexp = "foo",
  fixed = TRUE
)

expect_warning(
  1,
  regexp = "foo",
  fixed = TRUE
)
#> Error: 1 did not produce any warnings.

expect_error(
  stop("foo"),
  regexp = "foo",
  fixed = TRUE
)

expect_error(
  1,
  regexp = "foo",
  fixed = TRUE
)
#> Error: 1 did not throw an error.

Created on 2024-02-15 with reprex v2.1.0

billdenney avatar Feb 15 '24 14:02 billdenney

Somewhat more minimal reprex, but must be run interactively:

testthat::expect_message(1, "x", fixed = TRUE)

This is going to be a fun one to debug!

hadley avatar Apr 17 '24 22:04 hadley

I have isolated the issue to the edition_get() function.

When run interactively, edition_get() looks for the edition in the current directory, and in my case, it gets edition 3 because I'm using that in the current package. When run via reprex(), it is running in a different directory, so it gets the default edition 2.

The specific way that I isolated the error was to put a stop() before and after this line:

https://github.com/r-lib/testthat/blob/f060ccec365e1343ae926c53c215a423b295d7a8/R/expect-condition.R#L192

The stop() before that line triggered both interactively and with reprex(). The stop() after that line (inside the if block), triggered interactively but not with reprex().

I don't see any good fix. The ones that I think of are:

  1. To make reprex::reprex() aware of testthat by using local_edition() before changing the working directory.
  2. To make reprex::reprex() temporarily set some environmental variable indicating what the original directory was before changing to its new working directory (wd). And then, make edition_get() look for that new environmental variable after its current ways of looking.
  3. Do nothing, but then any edition-specific differences will always have different behavior in reprex() compared to when run either in tests or interactively.

billdenney avatar Aug 08 '24 11:08 billdenney

Ok, here's a reprex that succinctly illustrates the problem:

testthat::local_edition(2)
testthat::expect_message(1, "x", fixed = TRUE)
#> Error: 1 did not produce any messages.

testthat::local_edition(3)
testthat::expect_message(1, "x", fixed = TRUE)
#> Error: 1 did not throw the expected message.
#> Warning in testthat::expect_message(1, "x", fixed = TRUE): Arguments in `...` must be used.
#> ✖ Problematic argument:
#> • fixed = TRUE
#> ℹ Did you misspell an argument name?

Created on 2024-10-22 with reprex v2.1.0

hadley avatar Oct 22 '24 21:10 hadley