Skip to content

Commit 77ae470

Browse files
authored
Add input checking (#2155)
Fixes #1754
1 parent e5cd770 commit 77ae470

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+523
-31
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# testthat (development version)
22

3+
* `expect_*()` functions consistently and rigorously check their inputs (#1754).
34
* `JunitReporter()` no longer fails with `"no applicable method for xml_add_child"` for warnings outside of tests (#1913). Additionally, warnings now save their backtraces.
45
* `JunitReporter()` strips ANSI escapes in more placese (#1852, #2032).
56
* `try_again()` is now publicised. The first argument is now the number of retries, not tries (#2050).

R/compare.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ compare <- function(x, y, ...) {
1616
}
1717

1818
comparison <- function(equal = TRUE, message = "Equal") {
19-
stopifnot(is.logical(equal), length(equal) == 1)
20-
stopifnot(is.character(message))
19+
check_bool(equal)
20+
check_character(message)
2121

2222
structure(
2323
list(

R/expect-condition.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ expect_error <- function(
114114
info = NULL,
115115
label = NULL
116116
) {
117+
check_string(regexp, allow_null = TRUE, allow_na = TRUE)
118+
check_string(class, allow_null = TRUE)
119+
check_bool(inherit)
120+
117121
if (edition_get() >= 3) {
118122
expect_condition_matching_(
119123
"error",
@@ -158,6 +162,11 @@ expect_warning <- function(
158162
info = NULL,
159163
label = NULL
160164
) {
165+
check_string(regexp, allow_null = TRUE, allow_na = TRUE)
166+
check_string(class, allow_null = TRUE)
167+
check_bool(inherit)
168+
check_bool(all)
169+
161170
if (edition_get() >= 3) {
162171
if (!missing(all)) {
163172
warn("The `all` argument is deprecated")
@@ -207,6 +216,11 @@ expect_message <- function(
207216
info = NULL,
208217
label = NULL
209218
) {
219+
check_string(regexp, allow_null = TRUE, allow_na = TRUE)
220+
check_string(class, allow_null = TRUE)
221+
check_bool(inherit)
222+
check_bool(all)
223+
210224
if (edition_get() >= 3) {
211225
expect_condition_matching_(
212226
"message",
@@ -239,6 +253,10 @@ expect_condition <- function(
239253
info = NULL,
240254
label = NULL
241255
) {
256+
check_string(regexp, allow_null = TRUE, allow_na = TRUE)
257+
check_string(class, allow_null = TRUE)
258+
check_bool(inherit)
259+
242260
if (edition_get() >= 3) {
243261
expect_condition_matching_(
244262
"condition",

R/expect-equality.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ expect_equal <- function(
6565
) {
6666
act <- quasi_label(enquo(object), label)
6767
exp <- quasi_label(enquo(expected), expected.label)
68+
check_number_decimal(tolerance, min = 0, allow_null = TRUE)
6869

6970
if (edition_get() >= 3) {
7071
expect_waldo_equal_("equal", act, exp, info, ..., tolerance = tolerance)

R/expect-inheritance.R

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ NULL
4646
#' @export
4747
#' @rdname inheritance-expectations
4848
expect_type <- function(object, type) {
49-
stopifnot(is.character(type), length(type) == 1)
49+
check_string(type)
5050

5151
act <- quasi_label(enquo(object))
5252
act_type <- typeof(act$val)
@@ -69,6 +69,8 @@ expect_type <- function(object, type) {
6969
#' from `class`. If `TRUE`, checks that object has a class that's identical
7070
#' to `class`.
7171
expect_s3_class <- function(object, class, exact = FALSE) {
72+
check_bool(exact)
73+
7274
act <- quasi_label(enquo(object))
7375
act$class <- format_class(class(act$val))
7476
exp_lab <- format_class(class)
@@ -98,7 +100,7 @@ expect_s3_class <- function(object, class, exact = FALSE) {
98100
}
99101
}
100102
} else {
101-
abort("`class` must be a NA or a character vector")
103+
stop_input_type(class, c("a character vector", "NA"))
102104
}
103105

104106
pass(act$val)
@@ -187,7 +189,7 @@ isS3 <- function(x) is.object(x) && !isS4(x)
187189
#' @inheritParams expect_type
188190
#' @export
189191
expect_is <- function(object, class, info = NULL, label = NULL) {
190-
stopifnot(is.character(class))
192+
check_character(class)
191193
edition_deprecate(
192194
3,
193195
"expect_is()",

R/expect-known.R

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ expect_known_output <- function(
5858
print = FALSE,
5959
width = 80
6060
) {
61+
check_string(file)
62+
check_bool(update)
63+
check_bool(print)
64+
check_number_whole(width, min = 1)
6165
edition_deprecate(
6266
3,
6367
"expect_known_output()",
@@ -131,6 +135,10 @@ expect_output_file <- function(
131135
print = FALSE,
132136
width = 80
133137
) {
138+
check_string(file)
139+
check_bool(update)
140+
check_bool(print)
141+
check_number_whole(width, min = 1)
134142
# Code is a copy of expect_known_output()
135143
edition_deprecate(
136144
3,
@@ -158,6 +166,9 @@ expect_known_value <- function(
158166
label = NULL,
159167
version = 2
160168
) {
169+
check_string(file)
170+
check_bool(update)
171+
check_number_whole(version, min = 1)
161172
edition_deprecate(
162173
3,
163174
"expect_known_value()",

R/expect-length.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#' expect_length(1:10, 1)
1515
#' }
1616
expect_length <- function(object, n) {
17-
stopifnot(is.numeric(n), length(n) == 1)
17+
check_number_whole(n, min = 0)
1818

1919
act <- quasi_label(enquo(object))
2020
act$n <- length(act$val)

R/expect-match.R

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,11 @@ expect_no_match <- function(
7777
) {
7878
# Capture here to avoid environment-related messiness
7979
act <- quasi_label(enquo(object), label)
80-
stopifnot(is.character(regexp), length(regexp) == 1)
81-
stopifnot(is.character(act$val))
80+
check_character(object)
81+
check_string(regexp)
82+
check_bool(perl)
83+
check_bool(fixed)
84+
check_bool(all)
8285

8386
expect_match_(
8487
act = act,

R/expect-named.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ expect_named <- function(
3232
info = NULL,
3333
label = NULL
3434
) {
35+
check_bool(ignore.order)
36+
check_bool(ignore.case)
37+
3538
act <- quasi_label(enquo(object), label)
3639
act$names <- names(act$val)
3740

R/expect-output.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ expect_output <- function(
3030
label = NULL,
3131
width = 80
3232
) {
33+
check_number_whole(width, min = 1)
34+
3335
act <- quasi_capture(enquo(object), label, capture_output, width = width)
3436

3537
if (identical(regexp, NA)) {

0 commit comments

Comments
 (0)