Skip to content

Commit b2a8228

Browse files
committed
Bring expect_setequal() and friends up to code
* Approved way of wrapping `expect_error() * Modern style argument checking
1 parent 2896db2 commit b2a8228

File tree

4 files changed

+118
-40
lines changed

4 files changed

+118
-40
lines changed

R/expect-equality.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ expect_waldo_equal_ <- function(
123123
type,
124124
act,
125125
exp,
126-
info,
126+
info = NULL,
127127
...,
128128
trace_env = caller_env()
129129
) {

R/expect-setequal.R

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,10 @@ expect_setequal <- function(object, expected) {
2727
act <- quasi_label(enquo(object), arg = "object")
2828
exp <- quasi_label(enquo(expected), arg = "expected")
2929

30-
if (!is_vector(act$val) || !is_vector(exp$val)) {
31-
abort("`object` and `expected` must both be vectors")
32-
}
33-
30+
check_vector(object)
31+
check_vector(expected)
3432
if (!is.null(names(act$val)) && !is.null(names(exp$val))) {
35-
warn("expect_setequal() ignores names")
33+
testthat_warn("expect_setequal() ignores names")
3634
}
3735

3836
act_miss <- unique(act$val[!act$val %in% exp$val])
@@ -79,9 +77,10 @@ expect_mapequal <- function(object, expected) {
7977
act <- quasi_label(enquo(object), arg = "object")
8078
exp <- quasi_label(enquo(expected), arg = "expected")
8179

82-
if (!is_vector(act$val) || !is_vector(exp$val)) {
83-
abort("`object` and `expected` must both be vectors")
84-
}
80+
check_vector(object)
81+
check_map_names(object)
82+
check_vector(expected)
83+
check_map_names(expected)
8584

8685
# Length-0 vectors are OK whether named or unnamed.
8786
if (length(act$val) == 0 && length(exp$val) == 0) {
@@ -91,12 +90,9 @@ expect_mapequal <- function(object, expected) {
9190

9291
act_nms <- names(act$val)
9392
exp_nms <- names(exp$val)
94-
95-
check_names_ok(act_nms, "object")
96-
check_names_ok(exp_nms, "expected")
97-
9893
if (setequal(act_nms, exp_nms)) {
99-
return(expect_equal(act$val[exp_nms], exp$val))
94+
act <- labelled_value(act$val[exp_nms], act$lab)
95+
return(expect_waldo_equal_("equal", act, exp))
10096
}
10197

10298
act_miss <- setdiff(exp_nms, act_nms)
@@ -114,27 +110,16 @@ expect_mapequal <- function(object, expected) {
114110
pass(act$val)
115111
}
116112

117-
check_names_ok <- function(x, label) {
118-
if (anyDuplicated(x)) {
119-
stop("Duplicate names in `", label, "`: ", unique(x[duplicated(x)]))
120-
}
121-
if (any(x == "")) {
122-
stop("All elements in `", label, "` must be named")
123-
}
124-
}
125-
126113
#' @export
127114
#' @rdname expect_setequal
128115
expect_contains <- function(object, expected) {
129116
act <- quasi_label(enquo(object), arg = "object")
130117
exp <- quasi_label(enquo(expected), arg = "expected")
131118

132-
if (!is_vector(act$val) || !is_vector(exp$val)) {
133-
abort("`object` and `expected` must both be vectors")
134-
}
119+
check_vector(object)
120+
check_vector(expected)
135121

136122
exp_miss <- !exp$val %in% act$val
137-
138123
if (any(exp_miss)) {
139124
return(fail(paste0(
140125
act$lab,
@@ -155,12 +140,10 @@ expect_in <- function(object, expected) {
155140
act <- quasi_label(enquo(object), arg = "object")
156141
exp <- quasi_label(enquo(expected), arg = "expected")
157142

158-
if (!is_vector(act$val) || !is_vector(exp$val)) {
159-
abort("`object` and `expected` must both be vectors")
160-
}
143+
check_vector(object)
144+
check_vector(expected)
161145

162146
act_miss <- !act$val %in% exp$val
163-
164147
if (any(act_miss)) {
165148
return(fail(paste0(
166149
act$lab,
@@ -174,3 +157,40 @@ expect_in <- function(object, expected) {
174157

175158
pass(act$val)
176159
}
160+
161+
# Helpers ----------------------------------------------------------------------
162+
163+
check_map_names <- function(
164+
x,
165+
error_arg = caller_arg(x),
166+
error_call = caller_env()
167+
) {
168+
nms <- names2(x)
169+
170+
if (anyDuplicated(nms)) {
171+
dups <- unique(nms[duplicated(nms)])
172+
cli::cli_abort(
173+
c(
174+
"All elements in {.arg {error_arg}} must have unique names.",
175+
x = "Duplicate names: {.str {dups}}"
176+
),
177+
call = error_call
178+
)
179+
}
180+
if (any(nms == "")) {
181+
cli::cli_abort(
182+
"All elements in {.arg {error_arg}} must have names.",
183+
call = error_call
184+
)
185+
}
186+
}
187+
188+
check_vector <- function(
189+
x,
190+
error_arg = caller_arg(x),
191+
error_call = caller_env()
192+
) {
193+
if (!is_vector(x)) {
194+
stop_input_type(x, "a vector", arg = error_arg, call = error_call)
195+
}
196+
}

tests/testthat/_snaps/expect-setequal.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
# checks inputs
2+
3+
Code
4+
expect_setequal(sum, 1)
5+
Condition
6+
Error in `expect_setequal()`:
7+
! `object` must be a vector, not a primitive function.
8+
Code
9+
expect_setequal(1, sum)
10+
Condition
11+
Error in `expect_setequal()`:
12+
! `expected` must be a vector, not a primitive function.
13+
114
# useful message on failure
215

316
"actual" (`actual`) and "expected" (`expected`) don't have the same values.
@@ -37,6 +50,41 @@
3750
* Only in `expected`: 3, 4, 5, 6, 7, 8, 9, 10, 11, ...
3851

3952

53+
# check inputs
54+
55+
Code
56+
expect_mapequal(sum, named)
57+
Condition
58+
Error in `expect_mapequal()`:
59+
! `object` must be a vector, not a primitive function.
60+
Code
61+
expect_mapequal(named, sum)
62+
Condition
63+
Error in `expect_mapequal()`:
64+
! `expected` must be a vector, not a primitive function.
65+
Code
66+
expect_mapequal(unnamed, named)
67+
Condition
68+
Error in `expect_mapequal()`:
69+
! All elements in `object` must have names.
70+
Code
71+
expect_mapequal(named, unnamed)
72+
Condition
73+
Error in `expect_mapequal()`:
74+
! All elements in `expected` must have names.
75+
Code
76+
expect_mapequal(named, duplicated)
77+
Condition
78+
Error in `expect_mapequal()`:
79+
! All elements in `expected` must have unique names.
80+
x Duplicate names: "x"
81+
Code
82+
expect_mapequal(duplicated, named)
83+
Condition
84+
Error in `expect_mapequal()`:
85+
! All elements in `object` must have unique names.
86+
x Duplicate names: "x"
87+
4088
# expect_contains() gives useful message on failure
4189

4290
`x1` (`actual`) doesn't fully contain all the values in `x2` (`expected`).

tests/testthat/test-expect-setequal.R

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ test_that("warns if both inputs are named", {
2525
expect_warning(expect_setequal(c(a = 1), c(b = 1)), "ignores names")
2626
})
2727

28-
test_that("error for non-vectors", {
29-
expect_error(expect_setequal(sum, sum), "be vectors")
28+
test_that("checks inputs", {
29+
expect_snapshot(error = TRUE, {
30+
expect_setequal(sum, 1)
31+
expect_setequal(1, sum)
32+
})
3033
})
3134

3235
test_that("useful message on failure", {
@@ -72,14 +75,21 @@ test_that("fails if values don't match", {
7275
expect_failure(expect_mapequal(list(a = 1, b = 2), list(a = 1, b = 3)))
7376
})
7477

75-
test_that("error for non-vectors", {
76-
expect_error(expect_mapequal(sum, sum), "be vectors")
77-
expect_error(expect_mapequal(NULL, NULL), "be vectors")
78-
})
78+
test_that("check inputs", {
79+
unnamed <- list(1)
80+
named <- list(a = 1)
81+
duplicated <- list(x = 1, x = 2)
82+
83+
expect_snapshot(error = TRUE, {
84+
expect_mapequal(sum, named)
85+
expect_mapequal(named, sum)
86+
87+
expect_mapequal(unnamed, named)
88+
expect_mapequal(named, unnamed)
7989

80-
test_that("error if any unnamed values", {
81-
expect_error(expect_mapequal(list(1, b = 2), list(1, b = 2)))
82-
expect_error(expect_mapequal(list(1, b = 2), list(b = 2, 1)))
90+
expect_mapequal(named, duplicated)
91+
expect_mapequal(duplicated, named)
92+
})
8393
})
8494

8595
test_that("succeeds if comparing empty named and unnamed vectors", {

0 commit comments

Comments
 (0)