【问题标题】:distributing R package containing unit tests分发包含单元测试的 R 包
【发布时间】:2010-12-25 04:33:27
【问题描述】:

所以我决定将我的几个 R 函数放入一个包中,我正在阅读/学习 Writing R Extension。

它显然抱怨我做错了很多事情。

经过足够的谷歌搜索,我在这里提出了几个问题,这个问题是关于测试风格的:我使用的是RUnit,我喜欢让测试尽可能接近被测试的代码。这样我就不会忘记测试,并将测试用作技术文档的一部分。

例如:

fillInTheBlanks <- function(S) {
  ## NA in S are replaced with observed values

  ## accepts a vector possibly holding NA values and returns a vector
  ## where all observed values are carried forward and the first is
  ## carried backward.  cfr na.locf from zoo library.
  L <- !is.na(S)
  c(S[L][1], S[L])[1 + cumsum(L)]
}

test.fillInTheBlanks <- function() {
  checkEquals(fillInTheBlanks(c(1, NA, NA, 2, 3, NA, 4)), c(1, 1, 1, 2, 3, 3, 4))
  checkEquals(fillInTheBlanks(c(1, 2, 3, 4)), c(1, 2, 3, 4))
  checkEquals(fillInTheBlanks(c(NA, NA, 2, 3, NA, 4)), c(2, 2, 2, 3, 3, 4))
}

但R CMD check 发出 NOTE 行,像这样:

test.fillInTheBlanks: no visible global function definition for
  ‘checkEquals’

它抱怨我没有记录测试功能。

我真的不想为测试函数添加文档,而且我绝对不希望向 RUnit 包添加依赖项。

你认为我应该如何看待这个问题?

【问题讨论】:

    标签: unit-testing r software-distribution


    【解决方案1】:

    您将单元测试放在哪里?您可能不想将它们放入R 目录。更标准的方法是将它们放在inst\unitTests 下。看看this R-wiki page regarding the configuration.

    或者,您可以指定将在您的 NAMESPACE 中导出哪些文件,并通过扩展指定应该记录和不应该记录哪些函数。

    除此之外,理想情况下,您应该在调用 R CMD CHECK 时运行测试;这是设计的一部分。在这种情况下,您应该创建一个测试脚本来在单独的tests 目录中调用您的测试。而且您需要在该脚本中加载 RUnit 包(但您不需要使其成为包的依赖项)。

    编辑 1:

    关于你的失败,因为它找不到 checkEquals 函数:我会把你的函数改成这样:

    test.fillInTheBlanks <- function() {
      require(RUnit)
      checkEquals(fillInTheBlanks(c(1, NA, NA, 2, 3, NA, 4)), c(1, 1, 1, 2, 3, 3, 4))
      checkEquals(fillInTheBlanks(c(1, 2, 3, 4)), c(1, 2, 3, 4))
      checkEquals(fillInTheBlanks(c(NA, NA, 2, 3, NA, 4)), c(2, 2, 2, 3, 3, 4))
    }
    

    这样在调用函数时会加载包,否则会通知用户需要该包。

    编辑 2:

    来自"Writing R Extensions":

    请注意,包中的所有用户级对象都应记录在案;如果包 pkg 包含仅供“内部”使用的用户级对象,它应该提供一个文件 pkg-internal.Rd 记录所有此类对象,并明确说明这些对象不应由用户调用。参见例如以 R 发行版中的包网格源为例。请注意,广泛使用内部对象的包应在不需要记录这些对象时将这些对象隐藏在名称空间中(请参阅包名称空间)。

    您可以使用 pkg-internal.Rd 文件作为一种选择,但如果您打算拥有许多隐藏对象,这通常在 NAMESPACE 中的声明中处理。

    【讨论】:

    • 我将它们放在要测试的函数的定义之下。将编辑问题以使自己清楚。
    • 我明白了。然后使用 NAMESPACE 文件,如果您不想记录它们,请不要导出这些测试。除此之外,您可能希望在这些函数的顶部添加 require(RUnit),这样您就不必显式加载它。
    • 我把它们放在要测试的函数的定义之下(见编辑过的问题)。我会关注你的链接,看看我能做些什么,谢谢。
    • 在每个 test.functions 中添加了一个 require(RUnit),但这对 R CMD check 查找 RUnit 没有帮助。我添加了一个 pkg-internal.Rd 文件,为所有未记录的内部组件定义了一个别名。我发现解释比 NAMESPACE 更容易理解。
    • 第一个链接失效了。
    【解决方案2】:

    您是否加载了RUnit 包?

    您最好的选择可能是使用RUnit 查看包含现有代码的包。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-17
      • 2017-10-27
      • 2020-08-02
      • 2017-11-19
      • 2015-10-01
      • 1970-01-01
      • 2016-02-23
      • 1970-01-01
      相关资源
      最近更新 更多