Skip to content

devtools::test_coverage_active_file() and devtools::test() disagree on the error message to snapshot #2698

Closed as not planned

Description

@etiennebacher

Repo with reprex: https://github.com/etiennebacher/bug.testthat.coverage (tested in Positron and RStudio)

> packageVersion("covr")
[1] ‘3.6.5.9001’
> packageVersion("devtools")
[1] ‘2.5.2.9000’
> packageVersion("testthat")
[1] ‘3.3.2.9000’

Setup:

  • R/foo.R:

    f <- function(x) {
      if (x) {}
    }
  • tests/testthat/test-foo.R:

    test_that("foo", {
      expect_snapshot(f(x = logical(0)), error = TRUE)
    })
  • tests/testthat/_snaps/foo.md:

    # foo
    
      Code
        f(x = logical(0))
      Condition
        Error in `if (x) ...`:
        ! argument is of length zero
    

Bug:

  1. Open tests/testthat/test-foo.R in your editor (so that it is detected as the "active file")
  2. devtools::test() reports no issue
  3. devtools::test_coverage_active_file() is not happy with the snapshot:
> devtools::test_coverage_active_file()
── Failure: foo ──────────────────────────────────────────────────────────────────────────────────────────
Snapshot of code has changed:
    old                            | new                               
[1] Code                           | Code                           [1]
[2]   f(x = logical(0))            |   f(x = logical(0))            [2]
[3] Condition                      | Condition                      [3]
[4]   Error in `if (x) ...`:       -   Error in `if (...) NULL`:    [4]
[5]   ! argument is of length zero |   ! argument is of length zero [5]
* Run testthat::snapshot_accept("foo") to accept the change.
* Run testthat::snapshot_review("foo") to review the change.
Error:
! Test failed with 1 failure and 0 successes.

Activity

  1. etiennebacher commented on Jun 23, 2026

    @etiennebacher
    Author

    This is related to how covr works. Hopefully this helps someone.

    Why do snapshot messages change?

    When covr runs, it doesn't run tests right away but it instruments the functions in the package first. This means that it inserts pieces of code to count the number of times a line of code is run during the tests. For instance, this piece of code:

     if (x) {}

    would become this:

     if (if (TRUE) {
       covr:::count("...:2:7:...")
       x
    }) {}

    Therefore, when x has length 0 then the error:

    Error in `if (x) ...`:   ! argument is of length zero

    becomes:

    Error in `if (...) NULL`:    ! argument is of length zero

    because the ... represents the block:

    if (TRUE) {
       covr:::count("...:2:7:...")
       x
    }

    These are the two different messages that we see in the snapshots.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions