使用testthat测试数据集:替代<<-全局赋值的更佳方案
替代
<<-全局赋值的testthat数据集测试方案 我完全懂你用<<-的无奈——为了让后续测试能访问加载好的数据集,不得不污染全局环境,确实挺闹心的。这里有几个更优雅的替代方案,既能实现需求,又能保持测试的干净和独立:
方案1:用setup()函数共享变量
testthat提供了setup()函数,它会在当前测试文件的所有test_that块执行前运行一次,加载的变量会被放在测试专属的环境里,既不会污染全局环境,又能让所有测试块访问到:
# 在测试文件开头定义setup setup({ # 这里的nd是测试环境的局部变量,所有后续测试块都能访问 nd <- read_feather(DATAFILE) }) test_that("Data can be loaded", { # 验证加载过程无报错 expect_error(read_feather(DATAFILE), regexp = NA) }) test_that("Names are OK", { # 直接使用setup里加载好的nd expect_named(nd, nd_names) })
这个方案是最推荐的,既高效(只加载一次数据),又能保持测试的独立性,还不会留下全局变量的尾巴。
方案2:把相关测试放在同一个test_that块里
如果你的测试逻辑是紧密相关的(比如先测加载,再测列名),可以把它们放到同一个test_that块中,用局部赋值就够了:
test_that("Dataset meets basic validity requirements", { # 局部加载数据,仅在这个测试块内有效 nd <- read_feather(DATAFILE) # 测试加载成功 expect_error(nd, regexp = NA) # 测试列名符合预期 expect_named(nd, nd_names) })
这种方式的好处是测试逻辑更紧凑,变量完全局部化,不会有跨测试的状态污染问题。
方案3:封装加载函数(适合需要独立测试的场景)
如果你的测试需要完全独立(比如不想依赖setup的执行顺序),可以写一个加载数据的辅助函数,在每个需要的测试块里调用:
# 定义辅助加载函数 load_dataset <- function() { read_feather(DATAFILE) } test_that("Data can be loaded", { # 测试加载过程无报错 expect_error(load_dataset(), regexp = NA) }) test_that("Names are OK", { # 每个测试块独立加载数据 nd <- load_dataset() expect_named(nd, nd_names) })
这个方案的缺点是会重复加载数据(如果数据很大的话会影响测试速度),但好处是每个测试都是完全独立的,不会受其他测试的影响。
最后提醒下:尽量避免用<<-做测试,因为它会把变量留在全局环境,可能导致后续测试出现难以排查的问题,而且不符合测试的干净环境原则。
内容的提问来源于stack exchange,提问作者Rainer
相关产品推荐
相关产品推荐

