From 131c18aa139b81cc4d21d7b3e98e8ef181ef8807 Mon Sep 17 00:00:00 2001 From: selkamand Date: Fri, 12 Jan 2024 02:30:44 +1100 Subject: [PATCH] fix: assertions now provide informative errors when mandatory arguments are missing --- R/assert_create.R | 4 ++++ R/utils.R | 11 +++++++++++ tests/testthat/test-assert_create.R | 7 +++++++ 3 files changed, 22 insertions(+) diff --git a/R/assert_create.R b/R/assert_create.R index 74100e9..6770994 100644 --- a/R/assert_create.R +++ b/R/assert_create.R @@ -83,6 +83,10 @@ assert_create <- function(func, default_error_msg = NULL){ # Create body of assertion function body = quote({ + # Check mandatory arguments are all supplied + if(required_args_are_missing()) + cli::cli_abort('mandatory argument/s were not supplied') + # Setup some variables ( these will be useful later) if(is.null(arg_name)) arg_name <- deparse(match.call()[[2]]) diff --git a/R/utils.R b/R/utils.R index ae6ee18..a1502ef 100644 --- a/R/utils.R +++ b/R/utils.R @@ -110,3 +110,14 @@ func_arg_count <- function(func, dots = c("throw_error", "count_as_0", "count_as # lgl <- unlist(args) == substitute() # return(lgl) # } + +required_args_are_missing <- function (fun = sys.function(-1), ncall = 3) { + f_args <- formals(fun) + f_args <- f_args[vapply(f_args, is.symbol, FUN.VALUE = TRUE)] + f_args <- names(f_args) + f_args <- setdiff(f_args, "...") + test <- vapply(f_args, + function(x) missingArg(as.name(x), envir = parent.frame(ncall), eval = TRUE), + FUN.VALUE = TRUE) + return(any(test)) +} diff --git a/tests/testthat/test-assert_create.R b/tests/testthat/test-assert_create.R index 3ca5216..80a3682 100644 --- a/tests/testthat/test-assert_create.R +++ b/tests/testthat/test-assert_create.R @@ -110,7 +110,14 @@ cli::test_that_cli(configs = "plain", "assertion function works as expected with expect_snapshot(assert_between_min_and_max(2, min = 3, max = 5), error = TRUE) }) +cli::test_that_cli(configs = "plain", "created assertion() functions throw informative error when mandatory arguments are not supplied", { + f1 <- function(bob, billy) { return(TRUE) } + assert_f1 <- assertions::assert_create(f1, default_error_msg = 'this is an error message') + expect_error(assert_f1(), regexp = "mandatory argument/s were not supplied", fixed=TRUE) + expect_error(assert_f1(bob = 'a'), regexp = "mandatory argument/s were not supplied", fixed=TRUE) + expect_true(assert_f1('a', 'b')) +}) # Test Creation of Assertion Chains ----------------------------------------------------- cli::test_that_cli(configs = "plain", "assertion chains can evaluate expressions part and not get confused if they contain variable names", {