diff --git a/NEWS.md b/NEWS.md index b9e49d5c..3269ec02 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,9 @@ * Parameters were added for the `tab_pfn` model: `num_estimators()`, `softmax_temperature()`, `balance_probabilities()`, `average_before_softmax()`, and `training_set_limit()`. +* `parameters()` and the `grid_*()` functions give more information in the error message when non-parameter objects are passed in (#437). + + # dials 1.4.2 * `prop_terms()` is a new parameter object used for recipes that do supervised feature selection (#395). diff --git a/R/grids.R b/R/grids.R index 5b6f28c3..052a9c30 100644 --- a/R/grids.R +++ b/R/grids.R @@ -68,8 +68,21 @@ grid_regular.parameters <- function( original = TRUE, filter = NULL ) { - # test for NA and finalized - # test for empty ... + check_dots_empty() + + if (nrow(x) == 0) { + cli::cli_abort("At least one parameter object is required.") + } + # check for unknowns + for (i in seq_along(x$object)) { + check_param( + x$object[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = x$id[i] + ) + } + params <- x$object names(params) <- x$id grd <- make_regular_grid( @@ -91,6 +104,22 @@ grid_regular.list <- function( original = TRUE, filter = NULL ) { + check_dots_empty() + + if (length(x) == 0) { + cli::cli_abort("At least one parameter object is required.") + } + # check for unknowns + param_names <- names(x) + for (i in seq_along(x)) { + check_param( + x[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = param_arg_name(param_names[i], x[[i]], i) + ) + } + y <- parameters(x) params <- y$object names(params) <- y$id @@ -114,7 +143,19 @@ grid_regular.param <- function( original = TRUE, filter = NULL ) { - y <- parameters(list(x, ...)) + # check for unknowns + param_list <- list(x, ...) + param_names <- names(param_list) + for (i in seq_along(param_list)) { + check_param( + param_list[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = param_arg_name(param_names[i], param_list[[i]], i) + ) + } + + y <- parameters(param_list) params <- y$object names(params) <- y$id grd <- make_regular_grid( @@ -136,7 +177,7 @@ make_regular_grid <- function( ) { check_levels(levels, call = call) check_bool(original, call = call) - validate_params(..., call = call) + filter_quo <- enquo(filter) param_quos <- quos(...) params <- map(param_quos, eval_tidy) @@ -207,8 +248,21 @@ grid_random.parameters <- function( original = TRUE, filter = NULL ) { - # test for NA and finalized - # test for empty ... + check_dots_empty() + + if (nrow(x) == 0) { + cli::cli_abort("At least one parameter object is required.") + } + # check for unknowns + for (i in seq_along(x$object)) { + check_param( + x$object[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = x$id[i] + ) + } + params <- x$object names(params) <- x$id grd <- make_random_grid( @@ -224,6 +278,22 @@ grid_random.parameters <- function( #' @export #' @rdname grid_regular grid_random.list <- function(x, ..., size = 5, original = TRUE, filter = NULL) { + check_dots_empty() + + if (length(x) == 0) { + cli::cli_abort("At least one parameter object is required.") + } + # check for unknowns + param_names <- names(x) + for (i in seq_along(x)) { + check_param( + x[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = param_arg_name(param_names[i], x[[i]], i) + ) + } + y <- parameters(x) params <- y$object names(params) <- y$id @@ -247,7 +317,19 @@ grid_random.param <- function( original = TRUE, filter = NULL ) { - y <- parameters(list(x, ...)) + param_list <- list(x, ...) + # check for unknowns + param_names <- names(param_list) + for (i in seq_along(param_list)) { + check_param( + param_list[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = param_arg_name(param_names[i], param_list[[i]], i) + ) + } + + y <- parameters(param_list) params <- y$object names(params) <- y$id grd <- make_random_grid( @@ -269,7 +351,7 @@ make_random_grid <- function( ) { check_number_whole(size, min = 1, call = call) check_bool(original, call = call) - validate_params(..., call = call) + filter_quo <- enquo(filter) param_quos <- quos(...) params <- map(param_quos, eval_tidy) diff --git a/R/misc.R b/R/misc.R index 922ee704..17c1cfdf 100644 --- a/R/misc.R +++ b/R/misc.R @@ -292,3 +292,57 @@ check_unique <- function(x, ..., arg = caller_arg(x), call = caller_env()) { call = call ) } + +check_param <- function( + x, + ..., + allow_na = FALSE, + allow_unknown = FALSE, + arg = caller_arg(x), + call = caller_env() +) { + check_dots_empty() + + if (allow_na && all(is.na(x))) { + return(invisible(NULL)) + } + + if (inherits(x, "param")) { + if (allow_unknown || !has_unknowns(x)) { + return(invisible(NULL)) + } + + cli::cli_abort( + c( + x = "{.arg {arg}} must be a {.cls param} object without unknowns.", + i = "See the {.fn dials::finalize} function." + ), + call = call + ) + } + + what <- if (allow_unknown) { + "a object" + } else { + "a object without unknowns" + } + + stop_input_type( + x, + what, + ..., + allow_na = allow_na, + arg = arg, + call = call + ) +} + +param_arg_name <- function(name, x, position) { + if (!is.null(name) && nzchar(name)) { + return(name) + } + if (inherits(x, "param")) { + return(names(x$label)) + } + paste("Argument", position) +} diff --git a/R/parameters.R b/R/parameters.R index 03e03a65..44b89cfa 100644 --- a/R/parameters.R +++ b/R/parameters.R @@ -25,6 +25,11 @@ parameters <- function(x, ...) { #' @export #' @rdname parameters parameters.default <- function(x, ...) { + if (missing(x)) { + cli::cli_abort( + "No input provided. Please supply at least one parameter object." + ) + } cli::cli_abort( "{.cls parameters} objects cannot be created from {.obj_type_friendly {x}}." ) @@ -44,9 +49,14 @@ parameters.param <- function(x, ...) { parameters.list <- function(x, ...) { check_dots_empty() - elem_param <- purrr::map_lgl(x, inherits, "param") - if (!all(elem_param)) { - cli::cli_abort("The objects should all be {.cls param} objects.") + param_names <- names(x) + for (i in seq_along(x)) { + check_param( + x[[i]], + allow_na = FALSE, + allow_unknown = TRUE, + arg = param_arg_name(param_names[i], x[[i]], i) + ) } elem_name <- purrr::map_chr(x, \(.x) names(.x$label)) elem_id <- names(x) @@ -66,30 +76,6 @@ parameters.list <- function(x, ...) { ) } -param_or_na <- function(x) { - inherits(x, "param") || all(is.na(x)) -} - -check_list_of_param <- function(x, ..., call = caller_env()) { - check_dots_empty() - if (!is.list(x)) { - cli::cli_abort( - "{.arg object} must be a list of {.cls param} objects.", - call = call - ) - } - is_good_boi <- map_lgl(x, param_or_na) - if (!all(is_good_boi)) { - offenders <- which(!is_good_boi) - - cli::cli_abort( - "{.arg object} elements in the following positions must be {.code NA} or a - {.cls param} object: {offenders}.", - call = call - ) - } -} - #' Construct a new parameter set object #' #' @param name,id,source,component,component_id Character strings with the same @@ -120,7 +106,18 @@ parameters_constr <- function( check_character(source, call = call) check_character(component, call = call) check_character(component_id, call = call) - check_list_of_param(object, call = call) + if (!is.list(object)) { + cli::cli_abort("{.arg object} must be a list.", call = call) + } + for (i in seq_along(object)) { + check_param( + object[[i]], + allow_na = TRUE, + allow_unknown = TRUE, + arg = paste0("object[[", i, "]]"), + call = call + ) + } n_elements <- lengths(list(name, id, source, component, component_id, object)) n_elements_unique <- unique(n_elements) diff --git a/R/space_filling.R b/R/space_filling.R index 97f372bc..e5f4a655 100644 --- a/R/space_filling.R +++ b/R/space_filling.R @@ -118,8 +118,20 @@ grid_space_filling.parameters <- function( iter = 1000, original = TRUE ) { - # test for NA and finalized - # test for empty ... + check_dots_empty() + + if (nrow(x) == 0) { + cli::cli_abort("At least one parameter object is required.") + } + for (i in seq_along(x$object)) { + check_param( + x$object[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = x$id[i] + ) + } + params <- x$object names(params) <- x$id grd <- make_sfd( @@ -145,6 +157,21 @@ grid_space_filling.list <- function( iter = 1000, original = TRUE ) { + check_dots_empty() + + if (length(x) == 0) { + cli::cli_abort("At least one parameter object is required.") + } + param_names <- names(x) + for (i in seq_along(x)) { + check_param( + x[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = param_arg_name(param_names[i], x[[i]], i) + ) + } + y <- parameters(x) params <- y$object names(params) <- y$id @@ -172,7 +199,18 @@ grid_space_filling.param <- function( type = "any", original = TRUE ) { - y <- parameters(list(x, ...)) + param_list <- list(x, ...) + param_names <- names(param_list) + for (i in seq_along(param_list)) { + check_param( + param_list[[i]], + allow_na = FALSE, + allow_unknown = FALSE, + arg = param_arg_name(param_names[i], param_list[[i]], i) + ) + } + + y <- parameters(param_list) params <- y$object names(params) <- y$id grd <- make_sfd( @@ -215,7 +253,7 @@ make_sfd <- function( check_number_whole(iter, min = 1, call = call) check_bool(original, call = call) type <- rlang::arg_match(type, sfd_types) - validate_params(..., call = call) + param_quos <- quos(...) params <- map(param_quos, eval_tidy) p <- length(params) diff --git a/tests/testthat/_snaps/aaa_unknown.md b/tests/testthat/_snaps/aaa_unknown.md index b5062524..5ca42269 100644 --- a/tests/testthat/_snaps/aaa_unknown.md +++ b/tests/testthat/_snaps/aaa_unknown.md @@ -4,7 +4,7 @@ grid_regular(p1) Condition Error in `grid_regular()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -13,7 +13,7 @@ grid_regular(p2) Condition Error in `grid_regular()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -22,7 +22,7 @@ grid_regular(p3) Condition Error in `grid_regular()`: - x These arguments contain unknowns: `mtry` and `q`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -31,7 +31,7 @@ grid_random(p1) Condition Error in `grid_random()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -40,7 +40,7 @@ grid_random(p2) Condition Error in `grid_random()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -49,7 +49,7 @@ grid_space_filling(p1, type = "latin_hypercube") Condition Error in `grid_space_filling()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -58,7 +58,7 @@ grid_space_filling(p2, type = "latin_hypercube") Condition Error in `grid_space_filling()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -67,7 +67,7 @@ grid_space_filling(p1, type = "max_entropy") Condition Error in `grid_space_filling()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -76,7 +76,7 @@ grid_space_filling(p2, type = "max_entropy") Condition Error in `grid_space_filling()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -85,7 +85,7 @@ grid_regular(min_n(), q = mtry()) Condition Error in `grid_regular()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -94,7 +94,7 @@ grid_regular(mtry()) Condition Error in `grid_regular()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -103,7 +103,7 @@ grid_random(min_n(), q = mtry()) Condition Error in `grid_random()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -112,7 +112,7 @@ grid_random(mtry()) Condition Error in `grid_random()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -121,7 +121,7 @@ grid_regular(min_n(), q = mtry()) Condition Error in `grid_regular()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -130,7 +130,7 @@ grid_space_filling(mtry(), type = "latin_hypercube") Condition Error in `grid_space_filling()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -139,7 +139,7 @@ grid_space_filling(min_n(), q = mtry(), type = "max_entropy") Condition Error in `grid_space_filling()`: - x This argument contains unknowns: `q`. + x `q` must be a object without unknowns. i See the `dials::finalize()` function. --- @@ -148,6 +148,6 @@ grid_space_filling(mtry(), type = "max_entropy") Condition Error in `grid_space_filling()`: - x This argument contains unknowns: `mtry`. + x `mtry` must be a object without unknowns. i See the `dials::finalize()` function. diff --git a/tests/testthat/_snaps/grids.md b/tests/testthat/_snaps/grids.md index 4264d411..9ebb1360 100644 --- a/tests/testthat/_snaps/grids.md +++ b/tests/testthat/_snaps/grids.md @@ -91,6 +91,136 @@ Error in `grid_random()`: ! `original` must be `TRUE` or `FALSE`, not the string "yes". +# grid_random() errors with non-param inputs + + Code + grid_random() + Condition + Error in `UseMethod()`: + ! no applicable method for 'grid_random' applied to an object of class "NULL" + +--- + + Code + grid_random(penalty(), "min_n") + Condition + Error in `grid_random()`: + ! `Argument 2` must be a object without unknowns, not the string "min_n". + +--- + + Code + grid_random(mtry(), "min_n") + Condition + Error in `grid_random()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_random(list()) + Condition + Error in `grid_random()`: + ! At least one parameter object is required. + +--- + + Code + grid_random(list(penalty(), "min_n")) + Condition + Error in `grid_random()`: + ! `Argument 2` must be a object without unknowns, not the string "min_n". + +--- + + Code + grid_random(list(mtry(), "min_n")) + Condition + Error in `grid_random()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +# grid_random.parameters() checks for NA + + Code + grid_random(p) + Condition + Error in `grid_random()`: + ! `penalty` must be a object without unknowns, not `NA`. + +# grid_random() errors with params containing unknowns + + Code + grid_random(parameters(mtry())) + Condition + Error in `grid_random()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_random(mtry()) + Condition + Error in `grid_random()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_random(mtry(), sample_size()) + Condition + Error in `grid_random()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_random(list(mtry())) + Condition + Error in `grid_random()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_random(list(mtry_custom_name = mtry())) + Condition + Error in `grid_random()`: + x `mtry_custom_name` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_random(list(mtry(), sample_size())) + Condition + Error in `grid_random()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +# grid_random() errors with duplicate parameter ids + + Code + grid_random(penalty(), penalty()) + Condition + Error in `parameters()`: + x `id` must have unique values. + i Duplicates: "penalty" + +--- + + Code + grid_random(list(a = penalty(), a = penalty())) + Condition + Error in `parameters()`: + x `id` must have unique values. + i Duplicates: "a" + # grid_regular validates inputs Code @@ -115,6 +245,136 @@ Error in `grid_regular()`: ! `original` must be `TRUE` or `FALSE`, not the string "yes". +# grid_regular() errors with non-param inputs + + Code + grid_regular() + Condition + Error in `UseMethod()`: + ! no applicable method for 'grid_regular' applied to an object of class "NULL" + +--- + + Code + grid_regular(penalty(), "min_n") + Condition + Error in `grid_regular()`: + ! `Argument 2` must be a object without unknowns, not the string "min_n". + +--- + + Code + grid_regular(mtry(), "min_n") + Condition + Error in `grid_regular()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_regular(list()) + Condition + Error in `grid_regular()`: + ! At least one parameter object is required. + +--- + + Code + grid_regular(list(penalty(), "min_n")) + Condition + Error in `grid_regular()`: + ! `Argument 2` must be a object without unknowns, not the string "min_n". + +--- + + Code + grid_regular(list(mtry(), "min_n")) + Condition + Error in `grid_regular()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +# grid_regular.parameters() checks for NA + + Code + grid_regular(p) + Condition + Error in `grid_regular()`: + ! `penalty` must be a object without unknowns, not `NA`. + +# grid_regular() errors with params containing unknowns + + Code + grid_regular(parameters(mtry())) + Condition + Error in `grid_regular()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_regular(mtry()) + Condition + Error in `grid_regular()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_regular(penalty(), sample_size()) + Condition + Error in `grid_regular()`: + x `sample_size` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_regular(list(mtry())) + Condition + Error in `grid_regular()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_regular(list(mtry_custom_name = mtry())) + Condition + Error in `grid_regular()`: + x `mtry_custom_name` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_regular(list(mtry(), sample_size())) + Condition + Error in `grid_regular()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +# grid_regular() errors with duplicate parameter ids + + Code + grid_regular(penalty(), penalty()) + Condition + Error in `parameters()`: + x `id` must have unique values. + i Duplicates: "penalty" + +--- + + Code + grid_regular(list(a = penalty(), a = penalty())) + Condition + Error in `parameters()`: + x `id` must have unique values. + i Duplicates: "a" + # new param grid from conventional data frame Code diff --git a/tests/testthat/_snaps/misc.md b/tests/testthat/_snaps/misc.md index ee938fab..d2f03fbe 100644 --- a/tests/testthat/_snaps/misc.md +++ b/tests/testthat/_snaps/misc.md @@ -212,3 +212,61 @@ i This is an internal error that was detected in the dials package. Please report it at with a reprex () and the full backtrace. +# check_param() errors for param with unknowns when not allowed + + Code + check_param(mtry()) + Condition + Error: + x `mtry()` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + check_param(mtry(), allow_unknown = FALSE) + Condition + Error: + x `mtry()` must be a object without unknowns. + i See the `dials::finalize()` function. + +# check_param() errors for NA when not allowed + + Code + check_param(NA) + Condition + Error: + ! `NA` must be a object without unknowns, not `NA`. + +--- + + Code + check_param(NA, allow_na = FALSE) + Condition + Error: + ! `NA` must be a object without unknowns, not `NA`. + +# check_param() errors for non-param objects + + Code + check_param("not a param") + Condition + Error: + ! `"not a param"` must be a object without unknowns, not the string "not a param". + +# check_param() uses custom arg name + + Code + check_param("x", arg = "my_param") + Condition + Error: + ! `my_param` must be a object without unknowns, not the string "x". + +# check_param() error mentions NA when allowed + + Code + check_param("x", allow_na = TRUE) + Condition + Error: + ! `"x"` must be a object without unknowns or `NA`, not the string "x". + diff --git a/tests/testthat/_snaps/parameters.md b/tests/testthat/_snaps/parameters.md index 1765dcf8..1668b1eb 100644 --- a/tests/testthat/_snaps/parameters.md +++ b/tests/testthat/_snaps/parameters.md @@ -23,7 +23,7 @@ parameters_constr(ab, ab, ab, ab, ab, object = "not a params list") Condition Error: - ! `object` must be a list of objects. + ! `object` must be a list. --- @@ -32,7 +32,7 @@ parameters_constr(ab, ab, ab, ab, ab, object = list(penalty(), "not a param")) Condition Error: - ! `object` elements in the following positions must be `NA` or a object: 2. + ! `object[[2]]` must be a object or `NA`, not the string "not a param". --- @@ -67,7 +67,7 @@ parameters(list(a = mtry, a = penalty())) Condition Error in `parameters()`: - ! The objects should all be objects. + ! `a` must be a object, not a function. # updating @@ -178,3 +178,27 @@ Error in `parameters()`: ! objects cannot be created from a tibble. +# parameters() errors with non-param inputs + + Code + parameters() + Condition + Error in `parameters()`: + ! No input provided. Please supply at least one parameter object. + +--- + + Code + parameters(mtry(), "min_n") + Condition + Error in `parameters()`: + ! `Argument 2` must be a object, not the string "min_n". + +--- + + Code + parameters(list(mtry(), "min_n")) + Condition + Error in `parameters()`: + ! `Argument 2` must be a object, not the string "min_n". + diff --git a/tests/testthat/_snaps/space_filling.md b/tests/testthat/_snaps/space_filling.md index eec6b515..dca7a9ab 100644 --- a/tests/testthat/_snaps/space_filling.md +++ b/tests/testthat/_snaps/space_filling.md @@ -113,3 +113,133 @@ Error in `grid_space_filling()`: ! `original` must be `TRUE` or `FALSE`, not the string "yes". +# grid_space_filling() errors with non-param inputs + + Code + grid_space_filling() + Condition + Error in `UseMethod()`: + ! no applicable method for 'grid_space_filling' applied to an object of class "NULL" + +--- + + Code + grid_space_filling(penalty(), "min_n") + Condition + Error in `grid_space_filling()`: + ! `Argument 2` must be a object without unknowns, not the string "min_n". + +--- + + Code + grid_space_filling(mtry(), "min_n") + Condition + Error in `grid_space_filling()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_space_filling(list()) + Condition + Error in `grid_space_filling()`: + ! At least one parameter object is required. + +--- + + Code + grid_space_filling(list(penalty(), "min_n")) + Condition + Error in `grid_space_filling()`: + ! `Argument 2` must be a object without unknowns, not the string "min_n". + +--- + + Code + grid_space_filling(list(mtry(), "min_n")) + Condition + Error in `grid_space_filling()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +# grid_space_filling.parameters() checks for NA + + Code + grid_space_filling(p) + Condition + Error in `grid_space_filling()`: + ! `penalty` must be a object without unknowns, not `NA`. + +# grid_space_filling() errors with params containing unknowns + + Code + grid_space_filling(parameters(mtry())) + Condition + Error in `grid_space_filling()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_space_filling(mtry()) + Condition + Error in `grid_space_filling()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_space_filling(mtry(), sample_size()) + Condition + Error in `grid_space_filling()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_space_filling(list(mtry())) + Condition + Error in `grid_space_filling()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_space_filling(list(mtry_custom_name = mtry())) + Condition + Error in `grid_space_filling()`: + x `mtry_custom_name` must be a object without unknowns. + i See the `dials::finalize()` function. + +--- + + Code + grid_space_filling(list(mtry(), sample_size())) + Condition + Error in `grid_space_filling()`: + x `mtry` must be a object without unknowns. + i See the `dials::finalize()` function. + +# grid_space_filling() errors with duplicate parameter ids + + Code + grid_space_filling(penalty(), penalty()) + Condition + Error in `parameters()`: + x `id` must have unique values. + i Duplicates: "penalty" + +--- + + Code + grid_space_filling(list(a = penalty(), a = mtry())) + Condition + Error in `grid_space_filling()`: + x `a` must be a object without unknowns. + i See the `dials::finalize()` function. + diff --git a/tests/testthat/test-grids.R b/tests/testthat/test-grids.R index 3671df5a..743a42f8 100644 --- a/tests/testthat/test-grids.R +++ b/tests/testthat/test-grids.R @@ -108,12 +108,99 @@ test_that("grid_random validates inputs", { expect_snapshot(error = TRUE, grid_random(penalty(), original = "yes")) }) +test_that("grid_random() errors with non-param inputs", { + # no input at all + expect_snapshot(error = TRUE, grid_random()) + + # param method + expect_snapshot(error = TRUE, grid_random(penalty(), "min_n")) + expect_snapshot(error = TRUE, grid_random(mtry(), "min_n")) + + # list method + expect_snapshot(error = TRUE, grid_random(list())) + expect_snapshot(error = TRUE, grid_random(list(penalty(), "min_n"))) + expect_snapshot(error = TRUE, grid_random(list(mtry(), "min_n"))) +}) + +test_that("grid_random.parameters() checks for NA", { + p <- parameters(penalty()) + p <- update(p, penalty = NA) + expect_snapshot(error = TRUE, grid_random(p)) +}) + +test_that("grid_random() errors with params containing unknowns", { + # parameters method + expect_snapshot(error = TRUE, grid_random(parameters(mtry()))) + + # param method + expect_snapshot(error = TRUE, grid_random(mtry())) + expect_snapshot(error = TRUE, grid_random(mtry(), sample_size())) + + # list method + expect_snapshot(error = TRUE, grid_random(list(mtry()))) + expect_snapshot(error = TRUE, grid_random(list(mtry_custom_name = mtry()))) + expect_snapshot(error = TRUE, grid_random(list(mtry(), sample_size()))) +}) + +test_that("grid_random() errors with duplicate parameter ids", { + # param method + expect_snapshot(error = TRUE, grid_random(penalty(), penalty())) + + # list method + expect_snapshot(error = TRUE, grid_random(list(a = penalty(), a = penalty()))) +}) + test_that("grid_regular validates inputs", { expect_snapshot(error = TRUE, grid_regular(penalty(), levels = "three")) expect_snapshot(error = TRUE, grid_regular(penalty(), levels = -1)) expect_snapshot(error = TRUE, grid_regular(penalty(), original = "yes")) }) +test_that("grid_regular() errors with non-param inputs", { + # no input at all + expect_snapshot(error = TRUE, grid_regular()) + + # param method + expect_snapshot(error = TRUE, grid_regular(penalty(), "min_n")) + expect_snapshot(error = TRUE, grid_regular(mtry(), "min_n")) + + # list method + expect_snapshot(error = TRUE, grid_regular(list())) + expect_snapshot(error = TRUE, grid_regular(list(penalty(), "min_n"))) + expect_snapshot(error = TRUE, grid_regular(list(mtry(), "min_n"))) +}) + +test_that("grid_regular.parameters() checks for NA", { + p <- parameters(penalty()) + p <- update(p, penalty = NA) + expect_snapshot(error = TRUE, grid_regular(p)) +}) + +test_that("grid_regular() errors with params containing unknowns", { + # parameters method + expect_snapshot(error = TRUE, grid_regular(parameters(mtry()))) + + # param method + expect_snapshot(error = TRUE, grid_regular(mtry())) + expect_snapshot(error = TRUE, grid_regular(penalty(), sample_size())) + + # list method + expect_snapshot(error = TRUE, grid_regular(list(mtry()))) + expect_snapshot(error = TRUE, grid_regular(list(mtry_custom_name = mtry()))) + expect_snapshot(error = TRUE, grid_regular(list(mtry(), sample_size()))) +}) + +test_that("grid_regular() errors with duplicate parameter ids", { + # param method + expect_snapshot(error = TRUE, grid_regular(penalty(), penalty())) + + # list method + expect_snapshot( + error = TRUE, + grid_regular(list(a = penalty(), a = penalty())) + ) +}) + test_that("new param grid from conventional data frame", { x <- data.frame(num_comp = 1:3) diff --git a/tests/testthat/test-misc.R b/tests/testthat/test-misc.R index 18cec59c..3c06a392 100644 --- a/tests/testthat/test-misc.R +++ b/tests/testthat/test-misc.R @@ -119,3 +119,37 @@ test_that("vctrs-helpers-parameters", { dials:::df_size(2) ) }) + +test_that("check_param() passes for valid param objects", { + expect_no_error(check_param(penalty())) +}) + +test_that("check_param() passes for param with unknowns when allowed", { + expect_no_error(check_param(mtry(), allow_unknown = TRUE)) +}) + +test_that("check_param() errors for param with unknowns when not allowed", { + expect_snapshot(error = TRUE, check_param(mtry())) + expect_snapshot(error = TRUE, check_param(mtry(), allow_unknown = FALSE)) +}) + +test_that("check_param() passes for NA when allowed", { + expect_no_error(check_param(NA, allow_na = TRUE)) +}) + +test_that("check_param() errors for NA when not allowed", { + expect_snapshot(error = TRUE, check_param(NA)) + expect_snapshot(error = TRUE, check_param(NA, allow_na = FALSE)) +}) + +test_that("check_param() errors for non-param objects", { + expect_snapshot(error = TRUE, check_param("not a param")) +}) + +test_that("check_param() uses custom arg name", { + expect_snapshot(error = TRUE, check_param("x", arg = "my_param")) +}) + +test_that("check_param() error mentions NA when allowed", { + expect_snapshot(error = TRUE, check_param("x", allow_na = TRUE)) +}) diff --git a/tests/testthat/test-parameters.R b/tests/testthat/test-parameters.R index aef44ab1..c02f9382 100644 --- a/tests/testthat/test-parameters.R +++ b/tests/testthat/test-parameters.R @@ -120,6 +120,17 @@ test_that("parameters.default", { expect_snapshot(error = TRUE, parameters(tibble::as_tibble(mtcars))) }) +test_that("parameters() errors with non-param inputs", { + # no input at all + expect_snapshot(error = TRUE, parameters()) + + # param method + expect_snapshot(error = TRUE, parameters(mtry(), "min_n")) + + # list method + expect_snapshot(error = TRUE, parameters(list(mtry(), "min_n"))) +}) + # ------------------------------------------------------------------------------ # `[]` diff --git a/tests/testthat/test-space_filling.R b/tests/testthat/test-space_filling.R index 7323d17b..c13b6efb 100644 --- a/tests/testthat/test-space_filling.R +++ b/tests/testthat/test-space_filling.R @@ -151,7 +151,7 @@ test_that("sfd package designs AE", { dials_2_any <- grid_space_filling(prm, size = size, type = "any") sfd_2_any <- sfd::get_design(2, num_points = size, type = "any") - dials_2_ae <- grid_space_filling(prm, size = size, method = "audze_eglais") + dials_2_ae <- grid_space_filling(prm, size = size, type = "audze_eglais") sfd_2_ae <- sfd::get_design(2, num_points = size, type = "audze_eglais") names(sfd_2_ae) <- prm$id for (i in 1:2) { @@ -342,6 +342,54 @@ test_that("grid_space_filling validates inputs", { expect_snapshot(error = TRUE, grid_space_filling(penalty(), original = "yes")) }) +test_that("grid_space_filling() errors with non-param inputs", { + # no input at all + expect_snapshot(error = TRUE, grid_space_filling()) + + # param method + expect_snapshot(error = TRUE, grid_space_filling(penalty(), "min_n")) + expect_snapshot(error = TRUE, grid_space_filling(mtry(), "min_n")) + + # list method + expect_snapshot(error = TRUE, grid_space_filling(list())) + expect_snapshot(error = TRUE, grid_space_filling(list(penalty(), "min_n"))) + expect_snapshot(error = TRUE, grid_space_filling(list(mtry(), "min_n"))) +}) + +test_that("grid_space_filling.parameters() checks for NA", { + p <- parameters(penalty()) + p <- update(p, penalty = NA) + expect_snapshot(error = TRUE, grid_space_filling(p)) +}) + +test_that("grid_space_filling() errors with params containing unknowns", { + # parameters method + expect_snapshot(error = TRUE, grid_space_filling(parameters(mtry()))) + + # param method + expect_snapshot(error = TRUE, grid_space_filling(mtry())) + expect_snapshot(error = TRUE, grid_space_filling(mtry(), sample_size())) + + # list method + expect_snapshot(error = TRUE, grid_space_filling(list(mtry()))) + expect_snapshot( + error = TRUE, + grid_space_filling(list(mtry_custom_name = mtry())) + ) + expect_snapshot(error = TRUE, grid_space_filling(list(mtry(), sample_size()))) +}) + +test_that("grid_space_filling() errors with duplicate parameter ids", { + # param method + expect_snapshot(error = TRUE, grid_space_filling(penalty(), penalty())) + + # list method + expect_snapshot( + error = TRUE, + grid_space_filling(list(a = penalty(), a = mtry())) + ) +}) + test_that("pre-made designs respect the 'original argument", { # See issue #409