测试脚本如何通知 R CMD 检查它应该发出自定义消息?

发布于 2024-08-30 22:42:52 字数 2227 浏览 1 评论 0原文

我正在编写一个 R 包 (delftfews) 在办公室。我们使用 svUnit 进行单元测试。

我们描述新功能的过程:我们定义新的单元测试,最初标记为DEACTIVATED;我们一次激活一组测试并实现测试所描述的功能。几乎所有时候,我们都会有少量的 DEACTIVATED 测试,涉及可能被删除或将要实现的功能。

我的问题是:我可以更改 doSvUnit.R 以便在有 DEACTIVATED 测试的情况下,R CMD check pkg 发出一条注释(即自定义消息“NOTE”而不是“OK”)?

到目前为止,我们只看到活动测试不会给出错误:

.
.
* checking for unstated dependencies in tests ... OK
* checking tests ...
  Running ‘doSvUnit.R’
 OK
* checking PDF version of manual ... OK

如果所有测试都成功,那么这是可以的,但如果有跳过的测试,则不太好,如果有失败的测试,则肯定是错误的。在这种情况下,我实际上希望看到如下所示的注释或警告:

.
.
* checking for unstated dependencies in tests ... OK
* checking tests ...
  Running ‘doSvUnit.R’
 NOTE
6 test(s) were skipped.
 WARNING
1 test(s) are failing.
* checking PDF version of manual ... OK

到目前为止,我们必须打开 doSvUnit.Rout 来检查真实的测试结果。


我联系了 r-forge 和 CRAN 的两位维护者,他们向我指出了 R 的来源,特别是 testing.R 脚本。

如果我理解正确的话,要回答这个问题,我们需要修补 tools 包:

  • 使用 system 调用来调用测试目录中的脚本,
  • 输出(stdout 和 stderr)转到对于一个文件,
  • 有两种可能的结果:不好

所以我打开了一个R 上的更改请求,建议对返回状态进行位编码,位 0 表示错误(现在是这样),位-1 表示警告,bit-2 表示注意。

通过我的修改,生成此输出将很容易:

.
.
* checking for unstated dependencies in tests ... OK
* checking tests ...
  Running ‘doSvUnit.R’
 NOTE - please check doSvUnit.Rout.
 WARNING - please check doSvUnit.Rout.
* checking PDF version of manual ... OK

Brian Ripley 回答说“但是有几个包具有正确编写的单元测试 按要求发出信号。请在别处进行此讨论:R-bugs 不是提问的地方 问题。”并关闭了更改请求。


有人有提示吗?

I'm writing a R package (delftfews) here at office. we are using svUnit for unit testing.

our process for describing new functionality: we define new unit tests, initially marked as DEACTIVATED; one block of tests at a time we activate them and implement the function described by the tests. almost all the time we have a small amount of DEACTIVATED tests, relative to functions that might be dropped or will be implemented.

my problem/question is: can I alter the doSvUnit.R so that R CMD check pkg emits a NOTE (i.e. a custom message "NOTE" instead of "OK") in case there are DEACTIVATED tests?

as of now, we see only that the active tests don't give error:

.
.
* checking for unstated dependencies in tests ... OK
* checking tests ...
  Running ‘doSvUnit.R’
 OK
* checking PDF version of manual ... OK

which is all right if all tests succeed, but less all right if there are skipped tests and definitely wrong if there are failing tests. In this case, I'd actually like to see a NOTE or a WARNING like the following:

.
.
* checking for unstated dependencies in tests ... OK
* checking tests ...
  Running ‘doSvUnit.R’
 NOTE
6 test(s) were skipped.
 WARNING
1 test(s) are failing.
* checking PDF version of manual ... OK

As of now, we have to open the doSvUnit.Rout to check the real test results.


I contacted two of the maintainers at r-forge and CRAN and they pointed me to the sources of R, in particular the testing.R script.

if I understand it correctly, to answer this question we need patching the tools package:

  • scripts in the tests directory are called using a system call,
  • output (stdout and stderr) go to one single file,
  • there are two possible outcomes: ok or not ok,

so I opened a change request on R, proposing something like bit-coding the return status, bit-0 for ERROR (as it is now), bit-1 for WARNING, bit-2 for NOTE.

with my modification, it would be easy producing this output:

.
.
* checking for unstated dependencies in tests ... OK
* checking tests ...
  Running ‘doSvUnit.R’
 NOTE - please check doSvUnit.Rout.
 WARNING - please check doSvUnit.Rout.
* checking PDF version of manual ... OK

Brian Ripley replied "There are however several packages with properly written unit tests
that do signal as required. Please do take this discussion elsewhere: R-bugs is not the place to ask
questions." and closed the change request.


anybody has hints?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

扛起拖把扫天下 2024-09-06 22:42:52

您应该能够更改 doSvUnit.R 脚本以至少发出您所描述的警告和错误。您想要做的是运行测试,然后检查测试运行程序的返回值,并让 R 代码调用 warning() 或 stop()。

有关如何使用 RUnit 完成此操作的示例,请查看 Bioconductor 存储库中的 codetoolsBioC 包。相关代码位于 inst/templates 中并复制如下:

.test <- function(dir, pattern = ".*_test\\.R$")
{
    .failure_details <- function(result) {
        res <- result[[1L]]
        if (res$nFail > 0 || res$nErr > 0) {
            Filter(function(x) length(x) > 0,
                   lapply(res$sourceFileResults,
                          function(fileRes) {
                              names(Filter(function(x) x$kind != "success",
                                           fileRes))
                          }))
        } else list()
    }

    if (missing(dir)) {
        dir <- system.file("unitTests", package="@PKG@")
        if (!nzchar(dir)) {
            dir <- system.file("UnitTests", package="@PKG@")
            if (!nzchar(dir))
                stop("unable to find unit tests, no 'unitTests' dir")
        }
    }

    ## Run unit tests from the directory containing the test files.
    ## This allows tests to refer to data files with relative paths
    cwd <- getwd()
    on.exit(setwd(cwd))
    setwd(dir)

    require("RUnit", quietly=TRUE) || stop("RUnit package not found")
    RUnit_opts <- getOption("RUnit", list())
    RUnit_opts$verbose <- 0L
    RUnit_opts$silent <- TRUE
    RUnit_opts$verbose_fail_msg <- TRUE
    options(RUnit = RUnit_opts)
    suite <- defineTestSuite(name="@PKG@ RUnit Tests", dirs=getwd(),
                             testFileRegexp=pattern,
                             rngKind="default",
                             rngNormalKind="default")
    result <- runTestSuite(suite)
    cat("\n\n")
    printTextProtocol(result, showDetails=FALSE)
    if (length(details <- .failure_details(result)) >0) {
        cat("\nTest files with failing tests\n")
        for (i in seq_along(details)) {
            cat("\n  ", basename(names(details)[[i]]), "\n")
            for (j in seq_along(details[[i]])) {
                cat("    ", details[[i]][[j]], "\n")
            }
        }
        cat("\n\n")
        stop("unit tests failed for package @PKG@")
    }
    result
}

You should be able to alter the doSvUnit.R script to at least emit warnings and errors as you describe. What you want to do is to run the tests and then inspect the return value of the test runner and have R code that calls, warning() or stop().

For an example of how this was done using RUnit, take a look at the codetoolsBioC package in the Bioconductor repository. The relevant code is in inst/templates and copied below:

.test <- function(dir, pattern = ".*_test\\.R$")
{
    .failure_details <- function(result) {
        res <- result[[1L]]
        if (res$nFail > 0 || res$nErr > 0) {
            Filter(function(x) length(x) > 0,
                   lapply(res$sourceFileResults,
                          function(fileRes) {
                              names(Filter(function(x) x$kind != "success",
                                           fileRes))
                          }))
        } else list()
    }

    if (missing(dir)) {
        dir <- system.file("unitTests", package="@PKG@")
        if (!nzchar(dir)) {
            dir <- system.file("UnitTests", package="@PKG@")
            if (!nzchar(dir))
                stop("unable to find unit tests, no 'unitTests' dir")
        }
    }

    ## Run unit tests from the directory containing the test files.
    ## This allows tests to refer to data files with relative paths
    cwd <- getwd()
    on.exit(setwd(cwd))
    setwd(dir)

    require("RUnit", quietly=TRUE) || stop("RUnit package not found")
    RUnit_opts <- getOption("RUnit", list())
    RUnit_opts$verbose <- 0L
    RUnit_opts$silent <- TRUE
    RUnit_opts$verbose_fail_msg <- TRUE
    options(RUnit = RUnit_opts)
    suite <- defineTestSuite(name="@PKG@ RUnit Tests", dirs=getwd(),
                             testFileRegexp=pattern,
                             rngKind="default",
                             rngNormalKind="default")
    result <- runTestSuite(suite)
    cat("\n\n")
    printTextProtocol(result, showDetails=FALSE)
    if (length(details <- .failure_details(result)) >0) {
        cat("\nTest files with failing tests\n")
        for (i in seq_along(details)) {
            cat("\n  ", basename(names(details)[[i]]), "\n")
            for (j in seq_along(details[[i]])) {
                cat("    ", details[[i]][[j]], "\n")
            }
        }
        cat("\n\n")
        stop("unit tests failed for package @PKG@")
    }
    result
}
枕花眠 2024-09-06 22:42:52

我联系了 r-forge 和 CRAN 的两位维护者,他们向我指出了 R 的来源< /a>,特别是 check .R 脚本。

如果我理解正确的话:

  • 使用 system 调用来调用测试目录中的脚本,
  • 输出(stdout 和 stderr)转到一个文件,
  • 有两种可能的结果:ok不行
  • 要回答这个问题,我们需要修补库/工具包。

我在 R 上打开了 更改请求,我的第一个猜测是就像对返回状态进行位编码一样,bit-0 表示错误(就像现在一样),bit-1 表示警告,bit-2 表示注意。

在 doSvUnit.R 中,如果发生故障,我会使用 status 2 退出,如果跳过测试,我会使用 4 退出。

补丁看起来像这样:

Index: src/library/tools/R/testing.R
===================================================================
--- src/library/tools/R/testing.R   (revision 57214)
+++ src/library/tools/R/testing.R   (working copy)
@@ -352,10 +352,16 @@
         } else
             cmd <- paste("LANGUAGE=C", "R_TESTS=startup.Rs", cmd)
         res <- system(cmd)
-        if (res) {
+        if (res%/%4 %% 2) {
+            message("NOTE")
+        }
+        if (res%/%2 %% 2) {
+            message("WARNING")
+        }
+        if (res %% 2) {
             file.rename(outfile, paste(outfile, "fail", sep="."))
             return(1L)
         }
         savefile <- paste(outfile, "save", sep = "." )
         if (file.exists(savefile)) {
             message("  Comparing ", sQuote(outfile), " to ",

未打补丁的 R 将任何与 0 不同的内容视为错误。

I contacted two of the maintainers at r-forge and CRAN and they pointed me to the sources of R, in particular the check.R script.

if I understand it correctly:

  • scripts in the tests directory are called using a system call,
  • output (stdout and stderr) go to one single file,
  • there are two possible outcomes: ok or not ok,
  • to answer this question we need patching the library/tools package.

I opened a change request on R, my first guess is something like bit-coding the return status, bit-0 for ERROR (as it is now), bit-1 for WARNING, bit-2 for NOTE.

from doSvUnit.R, I would quit with status 2 in case of failures and 4 in case of skipped tests.

the patch would look like this:

Index: src/library/tools/R/testing.R
===================================================================
--- src/library/tools/R/testing.R   (revision 57214)
+++ src/library/tools/R/testing.R   (working copy)
@@ -352,10 +352,16 @@
         } else
             cmd <- paste("LANGUAGE=C", "R_TESTS=startup.Rs", cmd)
         res <- system(cmd)
-        if (res) {
+        if (res%/%4 %% 2) {
+            message("NOTE")
+        }
+        if (res%/%2 %% 2) {
+            message("WARNING")
+        }
+        if (res %% 2) {
             file.rename(outfile, paste(outfile, "fail", sep="."))
             return(1L)
         }
         savefile <- paste(outfile, "save", sep = "." )
         if (file.exists(savefile)) {
             message("  Comparing ", sQuote(outfile), " to ",

unpatched R sees anything different from 0 as ERROR.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文