在 R 包中测试与用户的交互

Test interaction with users in R package

我正在开发一个 R 包,其中一个函数通过 readline 通过标准输入实现与用户的交互。我现在想知道如何测试此函数的行为,最好使用 testthat 库。

似乎 test_that 函数假设用户输入的答案是 ""。我希望我可以测试用户可能输入的各种答案的行为条件。

下面是一个小示例代码。在实际开发中,marryme函数是在单独的文件中定义的,并导出到命名空间中。 devtools::test() 在最后一行给我一个错误,因为答案永远不会变成是。当用户输入 "y".

时,我想测试功能是否正确 returns true
library(testthat)

test_that("input", {
  marryme <- function() {
    ans <- readline("will you marry me? (y/n) > ")
    return(ans == "y")
  }

  expect_false(marryme())  # this is good
  expect_true(marryme())   # this is no good
})

通过自定义连接使用 readLines()

通过使用 readLines() 而不是 readline(),您可以定义连接,这允许您使用全局选项对其进行自定义。

您需要执行两个步骤:

  1. zzz.R 中的包中设置一个指向标准输入的默认选项:

    .onAttach <- function(libname, pkgname){
      options(mypkg.connection = stdin())
    }
    
  2. 在您的函数中,将 readline 更改为 readLines(n = 1) 并将 readLines() 中的连接设置为 getOption("mypkg.connection")

例子

根据您的 MWE:


    library(testthat)

    options(mypkg.connection = stdin())

    marryme <- function() {
      cat("will you marry me? (y/n) > ")
      ans <- readLines(con = getOption("mypkg.connection"), n = 1)
      cat("\n")
      return(ans == "y")
    }

    test_that("input", {

      f <- file()
      options(mypkg.connection = f)
      ans <- paste(c("n", "y"), collapse = "\n") # set this to the number of tests you want to run
      write(ans, f)

      expect_false(marryme())  # this is good
      expect_true(marryme())   # this is no good
      # reset connection
      options(mypkg.connection = stdin())
      # close the file
      close(f)
    })
#> will you marry me? (y/n) > 
#> will you marry me? (y/n) >