From 6edfc81b095dafbc16242558ee0ee4f47829f36e Mon Sep 17 00:00:00 2001 From: Justin Chase Date: Fri, 6 Nov 2026 09:56:03 +0000 Subject: [PATCH] Prepare 0.2.0 for CRAN submission - Tests that call glmnet or caret now skip when the package is absent; the suite passes with no suggested packages installed. - Examples that run in under two seconds are no longer in \donttest{}, and values computed inside guarded example blocks are printed. - DESCRIPTION: reflow the Description, spell out LASSO, require withr >= 2.4.0 (first release exporting local_seed()). - cran-comments: describe the checks actually run (with and without suggested packages), pre-empt the surname spelling NOTE, explain the scoped earth attach in fs_mars(), and drop unverifiable counts. - inst/WORDLIST: refresh for the reworked documentation. --- DESCRIPTION | 14 +++--- NEWS.md | 5 ++ R/fs_elastic.R | 8 ++-- R/fs_lasso.R | 6 +-- R/fs_mars.R | 8 ++-- R/fs_pca.R | 2 - R/fs_randomforest.R | 2 - R/fs_recursivefeature.R | 2 - R/fs_stepwise.R | 2 - R/fs_svm.R | 8 ++-- cran-comments.md | 62 +++++++++++++++--------- inst/WORDLIST | 87 ++++++++++++++++++++-------------- man/fs_elastic.Rd | 8 ++-- man/fs_lasso.Rd | 6 +-- man/fs_mars.Rd | 8 ++-- man/fs_pca.Rd | 2 - man/fs_randomforest.Rd | 2 - man/fs_recursivefeature.Rd | 2 - man/fs_stepwise.Rd | 2 - man/fs_svm.Rd | 8 ++-- tests/testthat/test-fs_lasso.R | 1 + tests/testthat/test-fs_svm.R | 1 + 22 files changed, 128 insertions(+), 118 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index ea4bebe..4d31dd9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -7,12 +7,12 @@ Authors@R: Description: Filter, wrapper, and embedded feature-selection methods behind a consistent set of functions that share one calling convention and one return type: univariate threshold filters, correlation and chi-squared - filters, information gain, LASSO and elastic net, Bayesian model - comparison, Boruta, recursive feature - elimination, random forest importance, multivariate adaptive regression - splines, support vector machine recursive feature elimination, stepwise - selection, and principal component / singular value decomposition - helpers. The implemented methods follow + filters, information gain, the least absolute shrinkage and selection + operator (LASSO) and elastic net, Bayesian model comparison, Boruta, + recursive feature elimination, random forest importance, multivariate + adaptive regression splines, support vector machine recursive feature + elimination, stepwise selection, and principal component / singular + value decomposition helpers. The implemented methods follow Tibshirani (1996) , Zou and Hastie (2005) , Friedman (1991) , @@ -35,7 +35,7 @@ Imports: parallel, stats, utils, - withr + withr (>= 2.4.0) Suggests: bigstatsr, Boruta, diff --git a/NEWS.md b/NEWS.md index 6c9a982..715cfa8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,11 @@ documentation page found and fixed silent wrong answers, hangs, crashes, and inaccurate claims. Fixes that change behavior are listed first under each review. Where a result changed, the old result was wrong. +* featR now requires withr 2.4.0 or later, the first release that exports + `local_seed()`. +* Examples that run in under two seconds are no longer wrapped in + `\donttest{}`, so `R CMD check` runs them. + ## First adversarial review A full statistical, methodological, and programmatic review. Every finding diff --git a/R/fs_elastic.R b/R/fs_elastic.R index 9cd279d..c1c9a79 100644 --- a/R/fs_elastic.R +++ b/R/fs_elastic.R @@ -660,7 +660,6 @@ elastic_check_categorical_levels <- function(data, predictors) { #' `use_pca = TRUE`).} #' \item{call}{The matched call.} #' @examples -#' \donttest{ #' if (requireNamespace("caret", quietly = TRUE) && #' requireNamespace("glmnet", quietly = TRUE) && #' requireNamespace("Matrix", quietly = TRUE)) { @@ -672,10 +671,9 @@ elastic_check_categorical_levels <- function(data, predictors) { #' ) #' df$y <- 2 * df$x1 - df$x2 + 0.1 * cos(seq_len(60) * 3) #' res <- fs_elastic(df, "y", alpha_seq = c(0.5, 1), seed = 1) -#' selected(res) -#' res$scores -#' res$details$best_alpha -#' } +#' print(selected(res)) +#' print(res$scores) +#' print(res$details$best_alpha) #' } #' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html) #' guide, which runs this function on a worked example. diff --git a/R/fs_lasso.R b/R/fs_lasso.R index abf6ee8..70ecfb5 100644 --- a/R/fs_lasso.R +++ b/R/fs_lasso.R @@ -531,7 +531,6 @@ lasso_importance <- function(coefs) { #' and `n_features` (number of design-matrix columns considered).} #' \item{call}{The matched call.} #' @examples -#' \donttest{ #' if (requireNamespace("glmnet", quietly = TRUE)) { #' n <- 100 #' df <- data.frame( @@ -541,9 +540,8 @@ lasso_importance <- function(coefs) { #' ) #' df$y <- 2 * df$x1 - 3 * df$x2 + rnorm(n) #' res <- fs_lasso(df, "y", seed = 123) -#' selected(res) -#' head(res$scores) -#' } +#' print(selected(res)) +#' print(head(res$scores)) #' } #' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html) #' guide, which runs this function on a worked example. diff --git a/R/fs_mars.R b/R/fs_mars.R index dcb4e9b..c8011e1 100644 --- a/R/fs_mars.R +++ b/R/fs_mars.R @@ -733,7 +733,6 @@ mars_evaluate <- function(model, test, target, verbose = FALSE) { #' } #' #' @examples -#' \donttest{ #' if (requireNamespace("caret", quietly = TRUE) && #' requireNamespace("earth", quietly = TRUE)) { #' # x1 and x2 drive y; x3 is noise @@ -745,10 +744,9 @@ mars_evaluate <- function(model, test, target, verbose = FALSE) { #' df$y <- 2 * df$x1 - df$x2 + rnorm(150, sd = 0.5) #' res <- fs_mars(df, "y", degree = 1, nprune = c(5, 10), #' number = 3, repeats = 1, seed = 42) -#' res$selected -#' res$scores -#' res$details$metrics -#' } +#' print(res$selected) +#' print(res$scores) +#' print(res$details$metrics) #' } #' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html) #' guide, which runs this function on a worked example. diff --git a/R/fs_pca.R b/R/fs_pca.R index 81c221f..b584c14 100644 --- a/R/fs_pca.R +++ b/R/fs_pca.R @@ -494,7 +494,6 @@ pca_plot <- function(pca_result, label_col) { #' res$var_explained #' head(res$pca_df) #' -#' \donttest{ #' if (requireNamespace("ggplot2", quietly = TRUE)) { #' # plot = FALSE (the default) draws nothing, but $plot is built anyway #' res <- fs_pca(iris, label_col = "Species", verbose = TRUE) @@ -503,7 +502,6 @@ pca_plot <- function(pca_result, label_col) { #' # plot = TRUE draws it as well #' res <- fs_pca(iris, label_col = "Species", plot = TRUE) #' } -#' } #' @seealso The [Dimensionality reduction](https://elkronos.github.io/featR/articles/dimensionality-reduction.html) #' guide, which runs this function on a worked example. #' @export diff --git a/R/fs_randomforest.R b/R/fs_randomforest.R index 78e3812..e9c0f9f 100644 --- a/R/fs_randomforest.R +++ b/R/fs_randomforest.R @@ -401,7 +401,6 @@ rf_pool_importance_sd <- function(forests) { #' } #' #' @examples -#' \donttest{ #' if (requireNamespace("randomForest", quietly = TRUE) && #' requireNamespace("caret", quietly = TRUE)) { #' res <- fs_randomforest( @@ -416,7 +415,6 @@ rf_pool_importance_sd <- function(forests) { #' print(res$scores) #' print(res$details$metrics) #' } -#' } #' @seealso The [Regularization and embedded importance](https://elkronos.github.io/featR/articles/regularization.html) #' guide, which runs this function on a worked example. #' @export diff --git a/R/fs_recursivefeature.R b/R/fs_recursivefeature.R index bf83488..036dcd6 100644 --- a/R/fs_recursivefeature.R +++ b/R/fs_recursivefeature.R @@ -823,7 +823,6 @@ rfe_train_final <- function(data_df, target, optimal_vars, #' } #' #' @examples -#' \donttest{ #' if (requireNamespace("caret", quietly = TRUE) && #' requireNamespace("randomForest", quietly = TRUE) && #' requireNamespace("e1071", quietly = TRUE)) { @@ -839,7 +838,6 @@ rfe_train_final <- function(data_df, target, optimal_vars, #' # the only held-out estimate on the object #' print(res$details$test_metrics) #' } -#' } #' @seealso The [Wrapper methods](https://elkronos.github.io/featR/articles/wrappers.html) #' guide, which runs this function on a worked example. #' @export diff --git a/R/fs_stepwise.R b/R/fs_stepwise.R index db85256..f9f044c 100644 --- a/R/fs_stepwise.R +++ b/R/fs_stepwise.R @@ -298,7 +298,6 @@ step_term_scores <- function(model, coefs, term_labels) { #' } #' #' @examples -#' \donttest{ #' if (requireNamespace("MASS", quietly = TRUE)) { #' res <- fs_stepwise(mtcars, target = "mpg", direction = "both") #' print(res$selected) @@ -309,7 +308,6 @@ step_term_scores <- function(model, coefs, term_labels) { #' refit <- stats::update(res$model, . ~ . - wt, data = mtcars) #' print(stats::formula(refit)) #' } -#' } #' @seealso The [Wrapper methods](https://elkronos.github.io/featR/articles/wrappers.html) #' guide, which runs this function on a worked example. #' @export diff --git a/R/fs_svm.R b/R/fs_svm.R index 1daa3a4..8c4433a 100644 --- a/R/fs_svm.R +++ b/R/fs_svm.R @@ -1166,7 +1166,6 @@ svm_performance <- function(predictions, actuals, task) { #' \item{call}{The matched call.} #' } #' @examples -#' \donttest{ #' if (requireNamespace("caret", quietly = TRUE) && #' requireNamespace("kernlab", quietly = TRUE) && #' requireNamespace("e1071", quietly = TRUE)) { @@ -1179,7 +1178,7 @@ svm_performance <- function(predictions, actuals, task) { #' tune_grid = data.frame(C = 1), #' seed = 42 #' ) -#' res$details$performance +#' print(res$details$performance) #' #' # SVM-RFE keeps the two most useful measurements #' sel <- fs_svm( @@ -1194,9 +1193,8 @@ svm_performance <- function(predictions, actuals, task) { #' n_features = 2, #' seed = 42 #' ) -#' sel$selected -#' sel$scores -#' } +#' print(sel$selected) +#' print(sel$scores) #' } #' @seealso The [Wrapper methods](https://elkronos.github.io/featR/articles/wrappers.html) #' guide, which runs this function on a worked example. diff --git a/cran-comments.md b/cran-comments.md index 1139c3a..ca9c5bc 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -4,10 +4,9 @@ This is an update of featR from 0.1.0 to 0.2.0. -It is a correctness release. Two statistical, methodological, and -programmatic reviews of the whole package fixed silent wrong answers, hangs, -crashes, and documentation that did not match behavior. Each fix has a -regression test; the test suite grew from 2013 to 2560 passing assertions. +It is a correctness release. A statistical, methodological, and programmatic +review of the whole package fixed silent wrong answers, hangs, crashes, and +documentation that did not match behavior. Each fix has a regression test. Some fixes change results or turn previously accepted, invalid input into an informative error. NEWS.md lists every change, with behavior changes first. @@ -15,35 +14,54 @@ informative error. NEWS.md lists every change, with behavior changes first. * GitHub Actions (r-lib/actions): macOS latest (R release), Windows latest (R release), Ubuntu latest (R devel, R release, R oldrel-1). -* Ubuntu (R release) with every suggested package except Boruta, bigstatsr, - and PRROC installed: 2560 passing assertions, 7 skipped for those packages. +* win-builder (R devel). +* Local Ubuntu (R release), `R CMD check --as-cran` twice: once with every + suggested package installed and `--run-donttest`, and once with no + suggested packages installed (`_R_CHECK_FORCE_SUGGESTS_=false`), to confirm + that examples, tests, and the vignette all run without them. ## R CMD check results 0 errors | 0 warnings | 0 notes +* Words that may be flagged as possibly misspelled in DESCRIPTION (Barnhill, + Boruta, Gabry, Guyon, Hastie, Kursa, Rudnicki, Tibshirani, Vapnik, Vehtari, + Zou) are author surnames from the cited references and the name of the + Boruta method. + ## Reverse dependencies There are no reverse dependencies on CRAN. ## Notes for reviewers +* As requested in the review of 0.1.0, Boruta is no longer in single quotes + in the Description (it names the method), and the methods are cited as + authors (year) . * All modeling engines (brms, caret, glmnet, randomForest, kernlab, earth, Boruta, and others) are in Suggests. Every function that needs one checks - availability with `requireNamespace()` and fails with an informative message - naming the packages to install. All examples that use a suggested package are - wrapped in `\donttest{}` behind `requireNamespace()` guards, and the test - suite skips those paths when the package is absent. -* `fs_bayes()` compiles a Stan program per candidate model. Its example is in - `\donttest{}`, guarded on brms being installed, limited to two - single-predictor models, and wrapped in `try()`, so a machine without a - working Stan toolchain skips it rather than failing. The equivalent call is - exercised in the test suite under `skip_on_cran()`. + availability with `requireNamespace()` and stops with a message naming the + packages to install. Examples that use a suggested package are guarded with + `requireNamespace()`. The tests skip those paths when a package is absent. +* Examples run in under 2 seconds each and are not wrapped in `\donttest{}`, + with two exceptions. `fs_bayes()` compiles a Stan program per candidate + model; its example is in `\donttest{}`, guarded on brms, limited to two + single-predictor models, and wrapped in `try()` so that a machine without a + working Stan toolchain skips it rather than failing. `fs_boruta()` is in + `\donttest{}` because its run time depends on the number of Boruta + iterations. +* `fs_mars()` with `search = "random"` and a factor outcome attaches earth (a + suggested package) for the duration of that call with + `withr::local_package()`, because caret's random-grid code for earth looks + up `contr.earth.response` on the search path. On exit, earth and any + packages it attached are detached, so the user's search path is unchanged. * Parallel execution is opt-in throughout. Every function defaults to a single - worker, requested worker counts are capped at the detected core count, and no - example or test uses more than two cores. -* The package never calls `set.seed()` unless the user supplies a `seed` - argument, and then restores the previous RNG state on exit via - `withr::local_seed()`. -* No package code writes to the user's file system, home directory, working - directory, or global environment. + worker, requested worker counts are capped at the detected core count, and + no example or test uses more than two cores. +* The package never seeds the random number generator unless the user + supplies a `seed` argument, and then restores the previous RNG state on exit + via `withr::local_seed()`. +* Package code writes nothing to the user's home directory, working + directory, or global environment. The only file it creates is a temporary + backing file under `tempdir()` for `fs_pca()` on very large data, which is + removed when the call returns. diff --git a/inst/WORDLIST b/inst/WORDLIST index 28b1a6b..de5a98d 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1,85 +1,102 @@ -ANOVA +1e +1e15 +1e154 +1e29 +1e31 +1e7 +2e +2x2 +6e AbsCoefficient +Ambroise Barnhill +Bonferroni Boruta Boruta's Breiman CMRG -Friedman +Diaconis +Downsampling Gabry Gelman Guyon Hastie Kursa L'Ecuyer -MASS +L1 +L2 MLmetrics -NZV +McLachlan +NaN OOB +PC1 +PC2 +PNAS POSIXt PRROC PSOCK -Preprocesses +Piironen Quinlan's +R2 RFE RSpectra -Rsquared Rudnicki +Sturges Tibshirani Vapnik Vehtari -Weston +WAIC Zou -auc +another's +aos backticked -bayes -bernoulli bigstatsr biserial -bonferroni -boruta -brm brms -cardinality casewise -collinear -computable -cv +data's denoising -df doParallel +doi downsampled -downsamples -downsampling +e1071 elpd +erroring featR's foreach fs furrr furrr's -generalizable ggplot +ggplot2 glmnet glmnet's -impute -iter +i11 +jss kernlab -mclapply -mtcars +kernlab's +linearities +loo's +multiclass pROC pbapply -pearson -prcomp -preprocesses +pkgdown +polycor +prevalidated randomForest -randomforest -resampled -rfe -sig -treedepth -uninterpretable -unpruned +resample's +rstan +s11222 +subsettable +survivorship +tb02080 +teardown +toolchain +uncentered +underflows +unscored unvalidated upsampled upsampling +v036 withr diff --git a/man/fs_elastic.Rd b/man/fs_elastic.Rd index 2ab770d..b625d75 100644 --- a/man/fs_elastic.Rd +++ b/man/fs_elastic.Rd @@ -220,7 +220,6 @@ the default summary function is used; a custom \code{summaryFunction} in } \examples{ -\donttest{ if (requireNamespace("caret", quietly = TRUE) && requireNamespace("glmnet", quietly = TRUE) && requireNamespace("Matrix", quietly = TRUE)) { @@ -232,10 +231,9 @@ if (requireNamespace("caret", quietly = TRUE) && ) df$y <- 2 * df$x1 - df$x2 + 0.1 * cos(seq_len(60) * 3) res <- fs_elastic(df, "y", alpha_seq = c(0.5, 1), seed = 1) - selected(res) - res$scores - res$details$best_alpha -} + print(selected(res)) + print(res$scores) + print(res$details$best_alpha) } } \seealso{ diff --git a/man/fs_lasso.Rd b/man/fs_lasso.Rd index b18cfad..16ae09c 100644 --- a/man/fs_lasso.Rd +++ b/man/fs_lasso.Rd @@ -193,7 +193,6 @@ either setting. The target must be free of NA, NaN and Inf. } \examples{ -\donttest{ if (requireNamespace("glmnet", quietly = TRUE)) { n <- 100 df <- data.frame( @@ -203,9 +202,8 @@ if (requireNamespace("glmnet", quietly = TRUE)) { ) df$y <- 2 * df$x1 - 3 * df$x2 + rnorm(n) res <- fs_lasso(df, "y", seed = 123) - selected(res) - head(res$scores) -} + print(selected(res)) + print(head(res$scores)) } } \seealso{ diff --git a/man/fs_mars.Rd b/man/fs_mars.Rd index ba2bf99..f05c66b 100644 --- a/man/fs_mars.Rd +++ b/man/fs_mars.Rd @@ -208,7 +208,6 @@ can be high even for a biased model. } \examples{ -\donttest{ if (requireNamespace("caret", quietly = TRUE) && requireNamespace("earth", quietly = TRUE)) { # x1 and x2 drive y; x3 is noise @@ -220,10 +219,9 @@ if (requireNamespace("caret", quietly = TRUE) && df$y <- 2 * df$x1 - df$x2 + rnorm(150, sd = 0.5) res <- fs_mars(df, "y", degree = 1, nprune = c(5, 10), number = 3, repeats = 1, seed = 42) - res$selected - res$scores - res$details$metrics -} + print(res$selected) + print(res$scores) + print(res$details$metrics) } } \seealso{ diff --git a/man/fs_pca.Rd b/man/fs_pca.Rd index 38c0024..ed4fbf6 100644 --- a/man/fs_pca.Rd +++ b/man/fs_pca.Rd @@ -133,7 +133,6 @@ res <- fs_pca(mtcars, num_pc = 2, label_col = "cyl") res$var_explained head(res$pca_df) -\donttest{ if (requireNamespace("ggplot2", quietly = TRUE)) { # plot = FALSE (the default) draws nothing, but $plot is built anyway res <- fs_pca(iris, label_col = "Species", verbose = TRUE) @@ -143,7 +142,6 @@ if (requireNamespace("ggplot2", quietly = TRUE)) { res <- fs_pca(iris, label_col = "Species", plot = TRUE) } } -} \seealso{ The \href{https://elkronos.github.io/featR/articles/dimensionality-reduction.html}{Dimensionality reduction} guide, which runs this function on a worked example. diff --git a/man/fs_randomforest.Rd b/man/fs_randomforest.Rd index e415eaf..fcfc753 100644 --- a/man/fs_randomforest.Rd +++ b/man/fs_randomforest.Rd @@ -289,7 +289,6 @@ relative to the target's magnitude. } } \examples{ -\donttest{ if (requireNamespace("randomForest", quietly = TRUE) && requireNamespace("caret", quietly = TRUE)) { res <- fs_randomforest( @@ -305,7 +304,6 @@ if (requireNamespace("randomForest", quietly = TRUE) && print(res$details$metrics) } } -} \seealso{ The \href{https://elkronos.github.io/featR/articles/regularization.html}{Regularization and embedded importance} guide, which runs this function on a worked example. diff --git a/man/fs_recursivefeature.Rd b/man/fs_recursivefeature.Rd index 316b0d6..aee6453 100644 --- a/man/fs_recursivefeature.Rd +++ b/man/fs_recursivefeature.Rd @@ -261,7 +261,6 @@ sequential run keeps caret's default \code{seeds = NA}. See } } \examples{ -\donttest{ if (requireNamespace("caret", quietly = TRUE) && requireNamespace("randomForest", quietly = TRUE) && requireNamespace("e1071", quietly = TRUE)) { @@ -278,7 +277,6 @@ if (requireNamespace("caret", quietly = TRUE) && print(res$details$test_metrics) } } -} \seealso{ The \href{https://elkronos.github.io/featR/articles/wrappers.html}{Wrapper methods} guide, which runs this function on a worked example. diff --git a/man/fs_stepwise.Rd b/man/fs_stepwise.Rd index 7757091..fd1bf26 100644 --- a/man/fs_stepwise.Rd +++ b/man/fs_stepwise.Rd @@ -125,7 +125,6 @@ written for the older interface still runs, without the effect it asked for. Check your argument names against the list below. } \examples{ -\donttest{ if (requireNamespace("MASS", quietly = TRUE)) { res <- fs_stepwise(mtcars, target = "mpg", direction = "both") print(res$selected) @@ -137,7 +136,6 @@ if (requireNamespace("MASS", quietly = TRUE)) { print(stats::formula(refit)) } } -} \seealso{ The \href{https://elkronos.github.io/featR/articles/wrappers.html}{Wrapper methods} guide, which runs this function on a worked example. diff --git a/man/fs_svm.Rd b/man/fs_svm.Rd index 0da6c9b..0401292 100644 --- a/man/fs_svm.Rd +++ b/man/fs_svm.Rd @@ -312,7 +312,6 @@ A seeded parallel run need not match a seeded sequential one. See } } \examples{ -\donttest{ if (requireNamespace("caret", quietly = TRUE) && requireNamespace("kernlab", quietly = TRUE) && requireNamespace("e1071", quietly = TRUE)) { @@ -325,7 +324,7 @@ if (requireNamespace("caret", quietly = TRUE) && tune_grid = data.frame(C = 1), seed = 42 ) - res$details$performance + print(res$details$performance) # SVM-RFE keeps the two most useful measurements sel <- fs_svm( @@ -340,9 +339,8 @@ if (requireNamespace("caret", quietly = TRUE) && n_features = 2, seed = 42 ) - sel$selected - sel$scores -} + print(sel$selected) + print(sel$scores) } } \seealso{ diff --git a/tests/testthat/test-fs_lasso.R b/tests/testthat/test-fs_lasso.R index db0e2cd..57df8bf 100644 --- a/tests/testthat/test-fs_lasso.R +++ b/tests/testthat/test-fs_lasso.R @@ -410,6 +410,7 @@ test_that("unbacktick_names restores escaped control characters", { }) test_that("fs_lasso handles a nonzero constant or tiny-unit predictor", { + skip_if_not_installed("glmnet") # REGRESSION: the design matrix was handed to glmnet as a sparse matrix, # whose standardization turns a constant column (or one whose squares # underflow) into a NaN lambda path; cv.glmnet() then failed with diff --git a/tests/testthat/test-fs_svm.R b/tests/testthat/test-fs_svm.R index 339ecc0..7b7f369 100644 --- a/tests/testthat/test-fs_svm.R +++ b/tests/testthat/test-fs_svm.R @@ -726,6 +726,7 @@ test_that("fs_svm rejects a fractional seed before any work", { }) test_that("encoded names keep literal backticks and backslashes (svm_encode)", { + skip_if_not_installed("caret") # REGRESSION: svm_encode() deleted every backtick from dummyVars()'s names, # but backtick() escapes a literal backtick as \`, so column "a`b" was # reported as "a\b" -- the name of a different column.