testthat icon indicating copy to clipboard operation
testthat copied to clipboard

Deprecated advice for expect_equivalent() is not equivalent

Open jarad opened this issue 1 year ago • 1 comments

In testthat 3.1.10 and waldo 0.5.1, the helpfile for expect_equivalent() says that this function is deprecated and suggests you to use expect_equal(ignore_attr = TRUE) instead. Unfortunately, these two are apparently not equivalent.

a <- 1
names(a) <- "a"
expect_equivalent(a, unname(a))                     # passes
expect_equal(a, unname(a), ignore_attr = TRUE) # fails

In addition, in the helpfile for waldo::compare() under ignore_attr, it says "For backward compatibility with all.equal(), you can also use TRUE, to all ignore differences in all attributes. This is not generally recommended as it is a blunt tool that will ignore many important functional differences."

The expect_equivalent() function was useful and the suggested alternative does not work in the use-case I am interested in.

jarad avatar Mar 27 '24 19:03 jarad

Minimal reprex:

library(testthat)
a <- 1
names(a) <- "a"
expect_equivalent(a, unname(a))
expect_equal(a, unname(a), ignore_attr = TRUE)
#> Error: `a` not equal to unname(a).
#> names for target but not for current

Created on 2024-04-17 with reprex v2.1.0

Hmmm, this is because waldo doesn't consider names to an attribute to be ignored. This needs to be documented better.

hadley avatar Apr 17 '24 22:04 hadley

Looks like this has been fixed in waldo:

library(testthat)
expect_equal(1, c(a = 1), ignore_attr = TRUE)
#> Error: 1 not equal to c(a = 1).
#> names for current but not for target

Created on 2024-11-05 with reprex v2.1.0

hadley avatar Nov 05 '24 18:11 hadley

Confusingly, base R apparently considers names as an attribute, so expect_equivalent(...) is not equivalent (as it were) to expect_equal(..., ignore_attr = TRUE), as one would expect from the man page, which says:

‘expect_equivalent()’ is deprecated in the 3rd edition. Instead use ‘expect_equal(ignore_attr = TRUE)’.

Instead, it seems one should use expect_equal(..., check.attributes = FALSE) ... ?

expect_equal(1, c(a = 1), check.attributes = FALSE) ## OK
expect_equivalent(1, c(a = 1))  ## OK
expect_equal(1, c(a = 1), ignore_attr = TRUE)
> Error: 1 not equal to c(a = 1).
> names for current but not for target

bbolker avatar Aug 02 '25 19:08 bbolker