Skip to content

Commit 4c1bc78

Browse files
committed
Merged origin/main into extract-test
2 parents bc9fa1f + fc95be8 commit 4c1bc78

File tree

9 files changed

+225
-20
lines changed

9 files changed

+225
-20
lines changed

NAMESPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ export(equals_reference)
7979
export(evaluate_promise)
8080
export(exp_signal)
8181
export(expect)
82+
export(expect_all_equal)
83+
export(expect_all_false)
84+
export(expect_all_true)
8285
export(expect_condition)
8386
export(expect_contains)
8487
export(expect_cpp_tests_pass)

NEWS.md

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

33
* New `extract_test()` function to extract a reprex from a failing expectation.
4+
* `expect_all_equal()`, `expect_all_true()`, and `expect_all_false()` are a new family of expectations that checks that every element of a vector has the same value. Compared to using `expect_true(all(...))` they give better failure messages (#1836, #2235).
45
* Expectations now consistently return the value of the first argument, regardless of whether the expectation succeeds or fails. The primary exception are `expect_message()` and friends which will return the condition. This shouldn't affect existing tests, but will make failures clearer when you chain together multiple expectations (#2246).
56
* `set_state_inspector()` gains `tolerance` argument and ignores minor FP differences by default (@mcol, #2237).
67
* `expect_vector()` fails, instead of erroring, if `object` is not a vector (@plietar, #2224).

R/expect-all.R

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#' Do you expect every value in a vector to have this value?
2+
#'
3+
#' These expectations are similar to `expect_true(all(x == "x"))`,
4+
#' `expect_true(all(x))` and `expect_true(all(!x))` but give more informative
5+
#' failure messages if the expectations are not met.
6+
#'
7+
#' @inheritParams expect_equal
8+
#' @export
9+
#' @examples
10+
#' x1 <- c(1, 1, 1, 1, 1, 1)
11+
#' expect_all_equal(x1, 1)
12+
#'
13+
#' x2 <- c(1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2)
14+
#' show_failure(expect_all_equal(x2, 1))
15+
#'
16+
#' # expect_all_true() and expect_all_false() are helpers for common cases
17+
#' set.seed(1016)
18+
#' show_failure(expect_all_true(rpois(100, 10) < 20))
19+
#' show_failure(expect_all_false(rpois(100, 10) > 20))
20+
expect_all_equal <- function(object, expected) {
21+
act <- quasi_label(enquo(object))
22+
exp <- quasi_label(enquo(expected))
23+
24+
expect_all_equal_(act, exp)
25+
invisible(act$val)
26+
}
27+
28+
#' @export
29+
#' @rdname expect_all_equal
30+
expect_all_true <- function(object) {
31+
act <- quasi_label(enquo(object))
32+
exp <- labelled_value(TRUE, "TRUE")
33+
34+
expect_all_equal_(act, exp)
35+
invisible(act$val)
36+
}
37+
38+
#' @export
39+
#' @rdname expect_all_equal
40+
expect_all_false <- function(object) {
41+
act <- quasi_label(enquo(object))
42+
exp <- labelled_value(FALSE, "FALSE")
43+
44+
expect_all_equal_(act, exp)
45+
invisible(act$val)
46+
}
47+
48+
49+
expect_all_equal_ <- function(act, exp, trace_env = caller_env()) {
50+
check_vector(act$val, error_call = trace_env, error_arg = "object")
51+
if (length(act$val) == 0) {
52+
cli::cli_abort("{.arg object} must not be empty.", call = trace_env)
53+
}
54+
55+
check_vector(exp$val, error_call = trace_env, error_arg = "expected")
56+
if (length(exp$val) != 1) {
57+
cli::cli_abort("{.arg expected} must be length 1.", call = trace_env)
58+
}
59+
60+
exp$val <- rep(exp$val, length(act$val))
61+
names(exp$val) <- names(act$val)
62+
expect_waldo_equal_(
63+
"Expected every element of %s to equal %s.",
64+
act,
65+
exp,
66+
tolerance = testthat_tolerance(),
67+
trace_env = trace_env
68+
)
69+
}

R/expect-constant.R

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@
1212
#' @examples
1313
#' expect_true(2 == 2)
1414
#' # Failed expectations will throw an error
15-
#' \dontrun{
16-
#' expect_true(2 != 2)
17-
#' }
18-
#' expect_true(!(2 != 2))
19-
#' # or better:
20-
#' expect_false(2 != 2)
15+
#' show_failure(expect_true(2 != 2))
2116
#'
22-
#' a <- 1:3
23-
#' expect_true(length(a) == 3)
24-
#' # but better to use more specific expectation, if available
25-
#' expect_equal(length(a), 3)
17+
#' # where possible, use more specific expectations, to get more informative
18+
#' # error messages
19+
#' a <- 1:4
20+
#' show_failure(expect_true(length(a) == 3))
21+
#' show_failure(expect_equal(length(a), 3))
22+
#'
23+
#' x <- c(TRUE, TRUE, FALSE, TRUE)
24+
#' show_failure(expect_true(all(x)))
25+
#' show_failure(expect_all_true(x))
2626
#' @name logical-expectations
2727
NULL
2828

_pkgdown.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ reference:
2727
- title: Expectations
2828
- subtitle: Values
2929
contents:
30+
- expect_all_equal
3031
- expect_gt
3132
- expect_length
3233
- expect_match

man/expect_all_equal.Rd

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

man/logical-expectations.Rd

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# validates its inputs
2+
3+
Code
4+
expect_all_equal(mean, 1)
5+
Condition
6+
Error in `expect_all_equal()`:
7+
! `object` must be a vector, not a function.
8+
Code
9+
expect_all_equal(logical(), 1)
10+
Condition
11+
Error in `expect_all_equal()`:
12+
! `object` must not be empty.
13+
Code
14+
expect_all_equal(1:10, mean)
15+
Condition
16+
Error in `expect_all_equal()`:
17+
! `expected` must be a vector, not a function.
18+
Code
19+
expect_all_equal(1:10, 1:2)
20+
Condition
21+
Error in `expect_all_equal()`:
22+
! `expected` must be length 1.
23+
24+
# can compare atomic vectors
25+
26+
Code
27+
expect_all_equal(x, TRUE)
28+
Condition
29+
Error:
30+
! Expected every element of `x` to equal TRUE.
31+
Differences:
32+
`actual[2:8]`: TRUE TRUE TRUE FALSE TRUE TRUE TRUE
33+
`expected[2:8]`: TRUE TRUE TRUE TRUE TRUE TRUE TRUE
34+
35+
# can compare named lists
36+
37+
Code
38+
expect_all_equal(x, list(1))
39+
Condition
40+
Error:
41+
! Expected every element of `x` to equal `list(1)`.
42+
Differences:
43+
`actual$c`: 2.0
44+
`expected$c`: 1.0
45+
46+
# truncates very long differences
47+
48+
Code
49+
expect_all_equal(x, FALSE)
50+
Condition
51+
Error:
52+
! Expected every element of `x` to equal FALSE.
53+
Differences:
54+
`actual`: TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
55+
`expected`: FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
56+

tests/testthat/test-expect-all.R

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
test_that("validates its inputs", {
2+
expect_snapshot(error = TRUE, {
3+
expect_all_equal(mean, 1)
4+
expect_all_equal(logical(), 1)
5+
expect_all_equal(1:10, mean)
6+
expect_all_equal(1:10, 1:2)
7+
})
8+
})
9+
10+
test_that("can compare atomic vectors", {
11+
x <- rep(TRUE, 10)
12+
expect_success(expect_all_equal(x, TRUE))
13+
14+
x[5] <- FALSE
15+
expect_snapshot_failure(expect_all_equal(x, TRUE))
16+
})
17+
18+
test_that("can compare named lists", {
19+
x <- list(a = 1, b = 1, c = 2, d = 1, e = 1)
20+
expect_snapshot_failure(expect_all_equal(x, list(1)))
21+
})
22+
23+
test_that("has tolerance enabled", {
24+
expect_success(expect_all_equal(1, 1L))
25+
})
26+
27+
test_that("truncates very long differences", {
28+
x <- rep(TRUE, 10)
29+
expect_snapshot_failure(expect_all_equal(x, FALSE))
30+
})
31+
32+
test_that("has TRUE and FALSE helpers", {
33+
x1 <- rep(TRUE, 10)
34+
x2 <- rep(FALSE, 10)
35+
expect_success(expect_all_true(x1))
36+
expect_success(expect_all_false(x2))
37+
})

0 commit comments

Comments
 (0)