R 包开发:测试在控制台中通过,但通过 devtools::test() 失败
R package development: tests pass in console, but fail via devtools::test()
我正在开发一个 R 包,它调用包 rstan
中的函数。作为 MWE,我的测试文件目前是这样设置的,使用从 rstan
的示例中逐字获取的代码:
library(testthat)
library(rstan)
# stan's own example
stancode <- 'data {real y_mean;} parameters {real y;} model {y ~ normal(y_mean,1);}'
mod <- stan_model(model_code = stancode, verbose = TRUE)
fit <- sampling(mod, data = list(y_mean = 0))
# I added this line, and it's the culprit
summary(fit)$summary
当我在控制台或通过 RStudio 中的“运行 测试”按钮 运行 这段代码时,不会抛出任何错误。但是,当我 运行 devtools::test()
时,我得到:
Error (test_moments.R:11:1): (code run outside of `test_that()`)
Error in `summary(fit)$summary`: $ operator is invalid for atomic vectors
而且这个错误绝对不会发生在最后一行代码的上游,因为删除最后一行允许 devtools::test()
到 运行 而不会出错。我正在 运行 更新软件包 devtools
和 rstan
。
似乎 devtools::test
在 S4 调度不以通常方式工作的设置中评估测试代码,至少对于您在测试文件中显式加载的包(在这种情况下 rstan
).结果,summary
分派到 summary.default
而不是 rstan
中为 class "stanfit"
.
实现的 S4 方法
您看到的行为可能与 testthat
存储库中的 this issue 有关,这似乎尚未解决。
这里是一个最小的例子,它试图阐明正在发生的事情,展示了一种可能的(公认的不方便的)解决方法。
pkgname <- "foo"
usethis::create_package(pkgname, rstudio = FALSE, open = FALSE)
setwd(pkgname)
usethis::use_testthat()
path_to_test <- file.path("tests", "testthat", "test-summary.R")
text <- "test_that('summary', {
library('rstan')
stancode <- 'data {real y_mean;} parameters {real y;} model {y ~ normal(y_mean,1);}'
mod <- stan_model(model_code = stancode, verbose = TRUE)
fit <- sampling(mod, data = list(y_mean = 0))
expect_identical(class(fit), structure('stanfit', package = 'rstan'))
expect_true(existsMethod('summary', 'stanfit'))
x <- summary(fit)
expect_error(x$summary)
expect_identical(x, summary.default(fit))
print(x)
f <- selectMethod('summary', 'stanfit')
y <- f(fit)
str(y)
})
"
cat(text, file = path_to_test)
devtools::test(".") # all tests pass
如果您的包实际上导入了 rstan
(在 NAMESPACE
意义上,而不是在 DESCRIPTION
意义上),那么 S4 调度似乎工作正常,大概是因为 devtools
在 运行 任何测试之前以“正确”的方式加载你的包及其依赖项。
cat("import(rstan)\n", file = "NAMESPACE")
newtext <- "test_that('summary', {
stancode <- 'data {real y_mean;} parameters {real y;} model {y ~ normal(y_mean,1);}'
mod <- stan_model(model_code = stancode, verbose = TRUE)
fit <- sampling(mod, data = list(y_mean = 0))
x <- summary(fit)
f <- selectMethod('summary', 'stanfit')
y <- f(fit)
expect_identical(x, y)
})
"
cat(newtext, file = path_to_test)
## You must restart your R session here. The current session
## is contaminated by the previous call to 'devtools::test',
## which loads packages without cleaning up after itself...
devtools::test(".") # all tests pass
如果您的测试失败 并且 您的包导入 rstan
,那么可能会发生其他事情,但如果没有您的最小版本,很难诊断包。
免责声明:不遗余力地导入 rstan
以解决一个相对晦涩的 devtools
问题应该被认为更多的是破解而不是修复,并相应地记录...
我正在开发一个 R 包,它调用包 rstan
中的函数。作为 MWE,我的测试文件目前是这样设置的,使用从 rstan
的示例中逐字获取的代码:
library(testthat)
library(rstan)
# stan's own example
stancode <- 'data {real y_mean;} parameters {real y;} model {y ~ normal(y_mean,1);}'
mod <- stan_model(model_code = stancode, verbose = TRUE)
fit <- sampling(mod, data = list(y_mean = 0))
# I added this line, and it's the culprit
summary(fit)$summary
当我在控制台或通过 RStudio 中的“运行 测试”按钮 运行 这段代码时,不会抛出任何错误。但是,当我 运行 devtools::test()
时,我得到:
Error (test_moments.R:11:1): (code run outside of `test_that()`)
Error in `summary(fit)$summary`: $ operator is invalid for atomic vectors
而且这个错误绝对不会发生在最后一行代码的上游,因为删除最后一行允许 devtools::test()
到 运行 而不会出错。我正在 运行 更新软件包 devtools
和 rstan
。
似乎 devtools::test
在 S4 调度不以通常方式工作的设置中评估测试代码,至少对于您在测试文件中显式加载的包(在这种情况下 rstan
).结果,summary
分派到 summary.default
而不是 rstan
中为 class "stanfit"
.
您看到的行为可能与 testthat
存储库中的 this issue 有关,这似乎尚未解决。
这里是一个最小的例子,它试图阐明正在发生的事情,展示了一种可能的(公认的不方便的)解决方法。
pkgname <- "foo"
usethis::create_package(pkgname, rstudio = FALSE, open = FALSE)
setwd(pkgname)
usethis::use_testthat()
path_to_test <- file.path("tests", "testthat", "test-summary.R")
text <- "test_that('summary', {
library('rstan')
stancode <- 'data {real y_mean;} parameters {real y;} model {y ~ normal(y_mean,1);}'
mod <- stan_model(model_code = stancode, verbose = TRUE)
fit <- sampling(mod, data = list(y_mean = 0))
expect_identical(class(fit), structure('stanfit', package = 'rstan'))
expect_true(existsMethod('summary', 'stanfit'))
x <- summary(fit)
expect_error(x$summary)
expect_identical(x, summary.default(fit))
print(x)
f <- selectMethod('summary', 'stanfit')
y <- f(fit)
str(y)
})
"
cat(text, file = path_to_test)
devtools::test(".") # all tests pass
如果您的包实际上导入了 rstan
(在 NAMESPACE
意义上,而不是在 DESCRIPTION
意义上),那么 S4 调度似乎工作正常,大概是因为 devtools
在 运行 任何测试之前以“正确”的方式加载你的包及其依赖项。
cat("import(rstan)\n", file = "NAMESPACE")
newtext <- "test_that('summary', {
stancode <- 'data {real y_mean;} parameters {real y;} model {y ~ normal(y_mean,1);}'
mod <- stan_model(model_code = stancode, verbose = TRUE)
fit <- sampling(mod, data = list(y_mean = 0))
x <- summary(fit)
f <- selectMethod('summary', 'stanfit')
y <- f(fit)
expect_identical(x, y)
})
"
cat(newtext, file = path_to_test)
## You must restart your R session here. The current session
## is contaminated by the previous call to 'devtools::test',
## which loads packages without cleaning up after itself...
devtools::test(".") # all tests pass
如果您的测试失败 并且 您的包导入 rstan
,那么可能会发生其他事情,但如果没有您的最小版本,很难诊断包。
免责声明:不遗余力地导入 rstan
以解决一个相对晦涩的 devtools
问题应该被认为更多的是破解而不是修复,并相应地记录...