我目前正在为R.开发graphical analysis package。我们正尝试使用Clean Code和Test-Driven Development(TDD)中的原则。但是,我们遇到了一个概念问题。
考虑以下简化示例。 Outer()
是我们在package中构建的功能,我们会将其列在NAMESPACE
文件中,以便将其公开给用户。 Inner()
是一个简短的(~5行)效用函数:
Outer <- function(...) {
Inner <- function(...) {
return(x)
}
return( Inner() )
}
我们package中的大多数用户公开函数都是简短的单行为Inner()
样式函数的集合,这些函数位于用户可以调用的单个Outer()
函数的保护伞下。 Granova.ds.ggplot()
就是一个例子。 Clean Code强烈提倡这种模块化设计,我们对结果非常满意。但是我们不知道如何为它构建单元测试,因为我们想要测试的函数在Granova.ds.ggplot()
函数的范围之外无法访问,因为我们设计了它。
我们遇到了几个想法/解决方案:
Inner()
之类的功能在设计上并非公开(它们不会在NAMESPACE
中导出),我们甚至不应该尝试测试它们。testthat
package wiki表示支持使用R CMD check
工作流程测试“非导出功能”。Outer()
函数以进行测试解决方案1似乎是一个警察。我们相信,特别是在R中,拥有一个称为各种简短,单一责任的实用方法的顶级函数是明智的。不能测试这样的方法看起来很愚蠢,就像那种类型的东西有解决方案,但我们还没有找到。
解决方案2可能有效,但到目前为止我们还没有开始工作。如果你尝试克隆our repository,那么采购inst/dev.R
我相信你会在测试输出中找到它无法找到函数InitializeGgplot()
,即使行中定义了said function granova.1w.ggplot()
的613-615。同样,在终端上运行R CMD check
似乎根本不执行任何测试。但是,它需要花费大量时间并向我们施加侮辱性错误: - (
解决方案3在某种意义上是务实的,但与总是朝着项目目标状态的目标相反。这对我们没有意义。
理想情况下,我们正在寻找一种方法来利用像testthat
这样的软件包在我们编码时快速提供反馈,并允许我们测试中存在的<{1}}之类的函数/ em>像Inner()
这样的函数。更好的方法是在不使用Outer()
的情况下完成它,由于我们的某些功能的三维复杂性每次运行几乎需要一分钟。
那么,我们缺少什么? TDD实践是否允许在R中测试外部/内部样式设置?如果他们这样做,我们怎样才能开发我们的包装?欢迎任何反馈,我会尽力回应任何不清楚的事情。
谢谢!
答案 0 :(得分:7)
如果Inner
实现了您要测试的非平凡功能,我建议将Inner
移至顶级,但不导出它。一般来说,我完全避免在其他函数中嵌套函数 - 它们很难测试。
你可以在开发过程中使用通常的测试功能进行测试,因为你可能只是在所有的R代码中采购而不用担心命名空间(至少我是如何开发的)。然后将R CMD check
与test_package
结合使用以确保测试在构建时仍然有效 - test_packages
运行包名称空间中的测试,以便它们可以测试未导出的函数。
答案 1 :(得分:6)
IMO这里没有问题 - Inner只是Outer的一个不可拆卸的部分,所以测试外部测试内部。你愿意测试匿名功能吗?同样在这里。