diff --git a/R/class-forecast.R b/R/class-forecast.R index 6992e0a0..a1541f80 100644 --- a/R/class-forecast.R +++ b/R/class-forecast.R @@ -272,7 +272,12 @@ is_forecast <- function(x) { # undesired situation if we set ...length() > 1 # is.data.table: when [.data.table returns an atomic vector, it's clear it # cannot be a valid forecast object, and it is likely intended by the user - if (data.table::is.data.table(out) && !is_dt_force_print) { + + # in addition, we also check for a maximum length. The reason is that + # print.data.table will internally subset the data.table before printing. + # this subsetting triggers the validation, which is not desired in this case. + # this is a hack and ideally, we'd do things differently. + if (nrow(out) > 30 && data.table::is.data.table(out) && !is_dt_force_print) { # check whether subset object passes validation validation <- try( assert_forecast(forecast = out, verbose = FALSE), @@ -280,9 +285,14 @@ is_forecast <- function(x) { ) if (inherits(validation, "try-error")) { cli_warn( + #nolint start: keyword_quote_linter c( - "!" = "Error in validating forecast object: {validation}" + "!" = "Error in validating forecast object: {validation}.", + "i" = "Note this error is sometimes related to `data.table`s `print`. + Run {.help [{.fun assert_forecast}](scoringutils::assert_forecast)} + to confirm." ) + #nolint end ) } } diff --git a/tests/testthat/test-class-forecast-nominal.R b/tests/testthat/test-class-forecast-nominal.R index f6c48fcc..74d5ab52 100644 --- a/tests/testthat/test-class-forecast-nominal.R +++ b/tests/testthat/test-class-forecast-nominal.R @@ -53,3 +53,18 @@ test_that("get_metrics.forecast_nominal() works as expected", { is.list(get_metrics(example_nominal)) ) }) + + +# ============================================================================== +# Printing +# ============================================================================== +test_that("Printing works as expected", { + suppressMessages( + expect_message( + expect_message( + capture.output(print(example_nominal)), + "Forecast type: nominal" + ), + "Forecast unit:") + ) +}) diff --git a/tests/testthat/test-class-forecast.R b/tests/testthat/test-class-forecast.R index 74fe1972..67f84967 100644 --- a/tests/testthat/test-class-forecast.R +++ b/tests/testthat/test-class-forecast.R @@ -146,14 +146,14 @@ test_that("print() works on forecast_* objects", { test_that("print() throws the expected messages", { test <- data.table::copy(example_point) class(test) <- c("point", "forecast", "data.table", "data.frame") - expect_warning( - suppressMessages( - expect_message( - capture.output(print(test)), - "Could not determine forecast type due to error in validation." - ) - ), - "Error in validating" + + # note that since introducing a length maximum for validation to be triggered, + # we don't throw a warning automatically anymore + suppressMessages( + expect_message( + capture.output(print(test)), + "Could not determine forecast type due to error in validation." + ) ) class(test) <- c("forecast_point", "forecast")