【问题标题】:Test interaction with users in R package在 R 包中测试与用户的交互
【发布时间】:2017-05-13 07:59:12
【问题描述】:

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

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

下面是一个小示例代码。在实际开发中,marryme函数定义在单独的文件中,并导出到命名空间。 devtools::test() 在最后一行给我一个错误,因为答案永远不会变成是。我想测试当用户输入"y"时函数是否正确返回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
})

【问题讨论】:

  • marryme 拆分为两个函数。将除readline 之外的所有内容放在一个函数中,您可以测试并使用包含readline 的包装函数调用该函数。顺便说一句,我不喜欢使用readline 进行用户输入。
  • 谢谢,@Roland。作为readline 的替代方案,您有什么建议?

标签: r readline r-package testthat


【解决方案1】:

将 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) >

【讨论】:

  • 这对于单个提示看起来不错,但我没有立即看到如何将其扩展到多个提示而不必为每个输入行设置一连串 options...跨度>
  • @MichaelChirico,无论有多少输入行,每个测试套件我只使用两个 options() 调用。挑战在于跟踪答案堆栈(在ans 变量中)。
  • 我收到这样的错误。 Error in nsenv[[f_name]](dirname(ns_path), package) : unbenutzte Argumente (dirname(ns_path), package) Ruft auf: suppressPackageStartupMessages ... &lt;Anonymous&gt; -&gt; load_code -&gt; &lt;Anonymous&gt; -&gt; run_pkg_hook
  • 我在.onAttach 方法中添加了libname, pkgname。否则会抛出 cmets 中提到的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-11
相关资源
最近更新 更多