test_that("stack returns ml_model with is_stacked = TRUE", { skip_if_not_installed("ranger") s <- iris_split() stacked <- ml_stack(s$train, "Species", seed = 42L, models = c("logistic"), meta = "logistic", cv_folds = 2L) expect_s3_class(stacked, "ml_model") expect_true(stacked$is_stacked) }) test_that("stack predict works", { s <- iris_split() stacked <- ml_stack(s$train, "Species", seed = 42L, models = c("logistic"), meta = "logistic", cv_folds = 2L) preds <- predict(stacked, newdata = s$valid) expect_equal(length(preds), nrow(s$valid)) }) test_that("stack regression works", { skip_if_not_installed("glmnet") s <- mtcars_split() stacked <- ml_stack(s$train, "mpg", seed = 42L, models = c("logistic"), meta = "linear", cv_folds = 2L) expect_equal(stacked$task, "regression") }) test_that("stack with default models (auto-selected)", { s <- iris_split() stacked <- ml_stack(s$train, "Species", seed = 42L, cv_folds = 2L) expect_s3_class(stacked, "ml_model") }) test_that("stack explain shows meta-learner feature weights", { s <- iris_split() stacked <- ml_stack(s$train, "Species", seed = 42L, models = c("logistic"), meta = "logistic", cv_folds = 2L) # explain on stacked model should work (meta is logistic) exp <- tryCatch(ml_explain(stacked), error = function(e) NULL) # May fail if stacked doesn't expose importance — that's acceptable for now expect_true(is.null(exp) || inherits(exp, "ml_explanation")) }) test_that("stack evaluate works", { s <- iris_split() stacked <- ml_stack(s$train, "Species", seed = 42L, models = c("logistic"), meta = "logistic", cv_folds = 2L) m <- ml_evaluate(stacked, s$valid) expect_s3_class(m, "ml_metrics") }) test_that("ml$stack() module style works", { s <- iris_split() stacked <- ml$stack(s$train, "Species", seed = 42L, models = c("logistic"), meta = "logistic", cv_folds = 2L) expect_s3_class(stacked, "ml_model") }) test_that("stack target not found raises data_error", { s <- iris_split() expect_error( ml_stack(s$train, "nonexistent", seed = 42L, cv_folds = 2L), class = "data_error" ) })