Skip to content

Commit 9133a91

Browse files
authored
Hotfix: Fix regression in how test depth is calculated; add exec index (#485)
1 parent f832d23 commit 9133a91

File tree

6 files changed

+95
-38
lines changed

6 files changed

+95
-38
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Encoding: UTF-8
22
Package: covr
33
Title: Test Coverage for Packages
4-
Version: 3.5.1.9002
4+
Version: 3.5.1.9003
55
Authors@R: c(
66
person("Jim", "Hester", email = "[email protected]", role = c("aut", "cre")),
77
person("Willem", "Ligtenberg", role = "ctb"),

NEWS.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
* Added `covr.record_tests` option. When `TRUE`, this enables the recording of
44
the trace of the tests being executed and adds an itemization of which tests
5-
result in the exeuction of each trace. For more details see
6-
`?covr.record_tests`
7-
`?covr.record_tests` (@dgkf, #463)
5+
result in the execution of each trace. For more details see
6+
`?covr.record_tests` (@dgkf, #463, #485)
87

98
* `package_coverage()` now sets the environment variable `R_TESTS` to the tests-startup.R file like R CMD check does (#420)
109

R/trace_calls.R

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ new_counter <- function(src_ref, parent_functions) {
117117
if (isTRUE(getOption("covr.record_tests", FALSE))) {
118118
.counters[[key]]$tests <- matrix(
119119
numeric(0L),
120-
ncol = 2,
121-
dimnames = list(c(), c("test", "depth")))
120+
ncol = 3L,
121+
# test index; call stack depth of covr:::count; execution order index
122+
dimnames = list(c(), c("test", "depth", "i")))
122123
}
123124

124125
key

R/trace_tests.R

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
#' execution.
1919
#'
2020
#' \item `$<srcref>$tests`: For each srcref count in the coverage object, a
21-
#' `$tests` field is now included which contains a matrix with two columns,
22-
#' "test" and "depth" which specify the test number (corresponding to the
23-
#' index of the test in `attr(,"tests")` and the stack depth into the target
24-
#' code where the trace was executed.
21+
#' `$tests` field is now included which contains a matrix with three columns,
22+
#' "test", "depth" and "i" which specify the test number (corresponding to the
23+
#' index of the test in `attr(,"tests")`, the stack depth into the target
24+
#' code where the trace was executed, and the order of execution for each
25+
#' test.
2526
#' }
2627
#'
2728
#' @section Test traces:
@@ -48,28 +49,42 @@
4849
#' fcode <- '
4950
#' f <- function(x) {
5051
#' if (x)
51-
#' TRUE
52+
#' f(!x)
5253
#' else
5354
#' FALSE
5455
#' }'
5556
#'
5657
#' options(covr.record_tests = TRUE)
5758
#' cov <- code_coverage(fcode, "f(TRUE)")
5859
#'
59-
#' # extract executed tests traces
60-
#' attr(cov, "tests")
61-
#' # $`/tmp/test.R:1:1:1:7:1:7:1:1`
62-
#' # $`/tmp/test.R:1:1:1:7:1:7:1:1`[[1]]
60+
#' # extract executed test code for the first test
61+
#' tail(attr(cov, "tests")[[1L]], 1L)
62+
#' # [[1]]
6363
#' # f(TRUE)
6464
#'
6565
#' # extract test itemization per trace
6666
#' cov[[3]][c("srcref", "tests")]
6767
#' # $srcref
68-
#' # TRUE
68+
#' # f(!x)
6969
#' #
7070
#' # $tests
71-
#' # test depth
72-
#' # [1,] 1 1
71+
#' # test depth i
72+
#' # [1,] 1 2 4
73+
#'
74+
#' # reconstruct the code path of a test by ordering test traces by [,"i"]
75+
#' lapply(cov, `[[`, "tests")
76+
#' # $`source.Ref2326138c55:4:6:4:10:6:10:4:4`
77+
#' # test depth i
78+
#' # [1,] 1 1 2
79+
#' #
80+
#' # $`source.Ref2326138c55:3:8:3:8:8:8:3:3`
81+
#' # test depth i
82+
#' # [1,] 1 1 1
83+
#' # [2,] 1 2 3
84+
#' #
85+
#' # $`source.Ref2326138c55:6:6:6:10:6:10:6:6`
86+
#' # test depth i
87+
#' # [1,] 1 2 4
7388
#'
7489
#' @name covr.record_tests
7590
NULL
@@ -88,10 +103,11 @@ count_test <- function(key) {
88103
# ignore if .counter was not created with record_tests (nested coverage calls)
89104
if (is.null(.counters[[key]]$tests)) return()
90105

91-
depth_into_pkg <- length(sys.calls()) - .current_test$frame - n_calls_into_covr + 1L
106+
depth_into_pkg <- length(sys.calls()) - length(.current_test$frames) - n_calls_into_covr + 1L
107+
.current_test$i <- .current_test$i + 1L
92108
.counters[[key]]$tests <- rbind(
93109
.counters[[key]]$tests,
94-
c(length(.counters$tests), depth_into_pkg)
110+
c(length(.counters$tests), depth_into_pkg, .current_test$i)
95111
)
96112
}
97113

@@ -146,6 +162,7 @@ update_current_test <- function(key) {
146162

147163
# build updated current test data, isolating relevant frames
148164
.current_test$trace <- syscalls[exec_frames]
165+
.current_test$i <- 0L
149166
.current_test$frames <- exec_frames
150167
.current_test$last_frame <- exec_frames[[Position(
151168
has_srcref,

man/covr.record_tests.Rd

Lines changed: 27 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-record_tests.R

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ test_that("covr.record_tests causes test traces to be recorded", {
1616

1717

1818
test_that("covr.record_tests records test indices and depth for each trace", {
19-
expect_equal(ncol(cov_func[[1]]$tests), 2L)
20-
expect_equal(colnames(cov_func[[1]]$tests), c("test", "depth"))
19+
expect_equal(ncol(cov_func[[1]]$tests), 3L)
20+
expect_equal(colnames(cov_func[[1]]$tests), c("test", "depth", "i"))
2121
})
2222

2323

@@ -63,11 +63,11 @@ test_that("covr.record_tests: merging coverage objects appends tests", {
6363
),
6464
`a:1:2:3:4:5:6:7:8` = list(
6565
value = 2L,
66-
tests = cbind(test = c(1, 2), depth = c(0, 1))
66+
tests = cbind(test = c(1, 2), depth = c(0, 1), i = c(1, 3))
6767
),
6868
`b:1:2:3:4:5:6:7:8` = list(
6969
value = 2L,
70-
tests = cbind(test = c(2), depth = c(0))
70+
tests = cbind(test = c(2), depth = c(0), i = c(2))
7171
)
7272
)
7373

@@ -86,11 +86,11 @@ test_that("covr.record_tests: merging coverage objects appends tests", {
8686
),
8787
`a:1:2:3:4:5:6:7:8` = list(
8888
value = 2L,
89-
tests = cbind(test = c(2), depth = c(0))
89+
tests = cbind(test = c(2), depth = c(0), i = c(1))
9090
),
9191
`c:1:2:3:4:5:6:7:8` = list(
9292
value = 2L,
93-
tests = cbind(test = c(2), depth = c(0))
93+
tests = cbind(test = c(2), depth = c(0), i = c(2))
9494
)
9595
)
9696

@@ -121,3 +121,28 @@ test_that("covr.record_tests: merging coverage test objects doesn't break defaul
121121
expect_silent(cov_merged <- merge_coverage(list(.counter_1, .counter_2)))
122122
expect_equal(cov_merged$`a:1:2:3:4:5:6:7:8`$value, 4L)
123123
})
124+
125+
126+
test_that("covr.record_tests: test that coverage objects contain expected test data", {
127+
fcode <- '
128+
f <- function(x) {
129+
if (x)
130+
f(!x)
131+
else
132+
FALSE
133+
}'
134+
135+
withr::with_options(c("covr.record_tests" = TRUE), cov <- code_coverage(fcode, "f(TRUE)"))
136+
137+
# expect 4 covr traces due to test
138+
expect_equal(sum(unlist(lapply(cov, function(i) nrow(i[["tests"]])))), 4L)
139+
140+
# expect that all tests have the same index
141+
expect_equal(unique(unlist(lapply(cov, function(i) i[["tests"]][,"test"]))), 1L)
142+
143+
# expect execution order index to be the same length as the number of traces
144+
expect_equal(length(unique(unlist(lapply(cov, function(i) i[["tests"]][,"i"])))), 4L)
145+
146+
# expect that there are two distinct stack depths (`if (x)` (@1), `TRUE` (@2), `FALSE` (@2))
147+
expect_equal(length(unique(unlist(lapply(cov, function(i) i[["tests"]][,"depth"])))), 2L)
148+
})

0 commit comments

Comments
 (0)