From 638b938c422083f7706cc68b87cb51b251e4f60f Mon Sep 17 00:00:00 2001 From: selkamand <73202525+selkamand@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:25:18 +1100 Subject: [PATCH] Improve missing-value errors for comparisons --- DESCRIPTION | 2 +- NEWS.md | 2 ++ R/assert_compare.R | 7 +++++++ R/has.R | 1 + tests/testthat/_snaps/assert_compare.md | 2 +- tests/testthat/test-assert_compare.R | 17 +++++++++++++++++ 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 1ba4752..f99ba70 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -33,6 +33,7 @@ Collate: 'is_functions.R' 'utils.R' 'assert_create.R' + 'has.R' 'assert_type.R' 'assert_compare.R' 'assert_dataframe.R' @@ -45,7 +46,6 @@ Collate: 'assert_null.R' 'assert_numerical.R' 'assert_packages.R' - 'has.R' 'assert_regex.R' 'assert_set.R' 'coverage_testing.R' diff --git a/NEWS.md b/NEWS.md index 2b87da3..05ee3af 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,8 @@ * Improved factor support for `assert_includes()` and `assert_excludes()` +* Improved missing-value errors for numeric comparison assertions (e.g., `assert_greater_than()` with `NaN`) + * Added `assert_connection()` * Added `assert_set_equal()` diff --git a/R/assert_compare.R b/R/assert_compare.R index c57bf00..1541b89 100644 --- a/R/assert_compare.R +++ b/R/assert_compare.R @@ -4,6 +4,7 @@ #' #' @include assert_create.R #' @include assert_type.R +#' @include has.R #' @include is_functions.R #' @include is_comparisons.R #' @param x An object to check @@ -26,6 +27,7 @@ #' @export assert_all_greater_than <- assert_create_chain( assert_numeric, + assert_no_missing, assert_create( is_greater_than, default_error_msg = "{.strong {arg_name}} must {ifelse(length(arg_value) > 1, 'all ', '')}be {.strong greater than} `{.strong {minimum}}`." @@ -84,6 +86,7 @@ assert_greater_than <- assert_create_chain( #' @export assert_all_greater_than_or_equal_to <- assert_create_chain( assert_numeric, + assert_no_missing, assert_create( is_greater_than_or_equal_to, default_error_msg = "{.strong {arg_name}} must {ifelse(length(arg_value) > 1, 'all ', '')}be {.strong greater than or equal to} `{.strong {minimum}}`." @@ -201,6 +204,7 @@ assert_equal <- assert_create(is_equal, default_error_msg = "{.strong {arg_name} #' @export assert_all_less_than <- assert_create_chain( assert_numeric, + assert_no_missing, assert_create( is_less_than, default_error_msg = "{.strong {arg_name}} must {ifelse(length(arg_value) > 1, 'all ', '')}be {.strong less than} `{.strong {maximum}}`." @@ -259,6 +263,7 @@ assert_less_than <- assert_create_chain( #' @export assert_all_less_than_or_equal_to <- assert_create_chain( assert_numeric, + assert_no_missing, assert_create( is_less_than_or_equal_to, default_error_msg = "{.strong {arg_name}} must {ifelse(length(arg_value) > 1, 'all ', '')}be {.strong less than or equal to} `{.strong {maximum}}`." @@ -315,6 +320,7 @@ assert_less_than_or_equal_to <- assert_create_chain( #' @export assert_all_between <- assert_create_chain( assert_numeric, + assert_no_missing, assert_create( is_between, default_error_msg = "{.strong {arg_name}} must {ifelse(length(arg_value) > 1, 'all ', '')}be {.strong between} {.strong {minimum}} and {.strong {maximum}} {ifelse(inclusive, '(inclusive)', '(exclusive)')}." @@ -346,6 +352,7 @@ assert_all_between <- assert_create_chain( #' @export assert_between <- assert_create_chain( assert_number, + assert_no_missing, assert_create( is_between, default_error_msg = "{.strong {arg_name}} must be {.strong between} {.strong {minimum}} and {.strong {maximum}} {ifelse(inclusive, '(inclusive)', '(exclusive)')}." diff --git a/R/has.R b/R/has.R index dc8cbca..df1718f 100644 --- a/R/has.R +++ b/R/has.R @@ -136,6 +136,7 @@ has_class <- function(x, class){ #' This function asserts that the input vector has no missing values (`NA`) and aborts #' with an error message if it does. #' +#' @include assert_create.R #' @param x A vector. #' @param msg A character string containing the error message to display if `x` has missing values. #' @inheritParams common_roxygen_params diff --git a/tests/testthat/_snaps/assert_compare.md b/tests/testthat/_snaps/assert_compare.md index 354205d..2ee3e74 100644 --- a/tests/testthat/_snaps/assert_compare.md +++ b/tests/testthat/_snaps/assert_compare.md @@ -203,7 +203,7 @@ Code assert_all_greater_than_or_equal_to(c(4, NA), 3) Condition - Error in `compare()`: + Error: ! 'c(4, NA)' must have no missing values! Found 1 # assert_greater_than_or_equal_to() works [plain] diff --git a/tests/testthat/test-assert_compare.R b/tests/testthat/test-assert_compare.R index 893c797..d7c8dec 100644 --- a/tests/testthat/test-assert_compare.R +++ b/tests/testthat/test-assert_compare.R @@ -196,6 +196,23 @@ cli::test_that_cli("assert_between() works", config = "plain", { expect_error(assert_between(NULL, 1, 4), "is not a number", fixed = TRUE) }) +cli::test_that_cli("numeric comparison assertions reject NaN with a missing-values error", config = "plain", { + expect_error(assert_greater_than(NaN, 2), "must have no missing values", fixed = FALSE) + expect_error(assert_all_greater_than(c(2, NaN), 1), "must have no missing values", fixed = FALSE) + + expect_error(assert_greater_than_or_equal_to(NaN, 2), "must have no missing values", fixed = FALSE) + expect_error(assert_all_greater_than_or_equal_to(c(2, NaN), 2), "must have no missing values", fixed = FALSE) + + expect_error(assert_less_than(NaN, 2), "must have no missing values", fixed = FALSE) + expect_error(assert_all_less_than(c(1, NaN), 2), "must have no missing values", fixed = FALSE) + + expect_error(assert_less_than_or_equal_to(NaN, 2), "must have no missing values", fixed = FALSE) + expect_error(assert_all_less_than_or_equal_to(c(1, NaN), 2), "must have no missing values", fixed = FALSE) + + expect_error(assert_between(NaN, 1, 3), "must have no missing values", fixed = FALSE) + expect_error(assert_all_between(c(1, NaN), 0, 2), "must have no missing values", fixed = FALSE) +}) + cli::test_that_cli("assert_identical() works", config = "plain", { # Passes