{testthat} 带有 `expect_match` 的 `quasi_label` 抛出“错误:无效的参数类型”

问题描述

我是 {testthat} 的新手,正在为一个修改字符串的函数构建测试,并期望为某些输入模式生成特定的输出

作为一个例子(下面的reprex),add_excitement 在它的输入字符串中添加一个感叹号。当输入“hello”时,它应该返回“hello!”;当给出任何其他输入时,它应该返回“你好!”。我想对一系列模式进行 {testthat} 行为并返回信息性错误,这些错误指定导致错误的模式。

基于 {testthat} 包文档,我相信我应该使用 expect_match。但是,这会引发“无效参数类型”错误,而 expect_identical 有效。我不明白为什么会这样。我的问题是:

  • 为什么 expect_identical 而不是 expect_match 接受 quasi_label 参数?
  • 出于我的目的,我可以使用 expect_identical 而不是 expect_match 吗,否则会不会冒其他错误的风险?

这是一个reprex:

library(testthat)
library(purrr)

patterns = c("hello","goodbye","cheers")
add_excitement <- function(pattern) paste0(pattern,"!")

# For a single pattern
show_failure(expect_identical(add_excitement(!!patterns[2]),"hello!"))
#> Failed expectation:
#> add_excitement("goodbye") not identical to "hello!".
#> 1/1 mismatches
#> x[1]: "goodbye!"
#> y[1]: "hello!"
try(
  show_failure(expect_match(add_excitement(!!patterns[2]),"hello!",fixed = TRUE,all = TRUE))
)
#> Error in !patterns[2] : invalid argument type

# For multiple patterns
purrr::map(
  patterns,~ show_failure(expect_identical(add_excitement(!!.),"hello!"))
)
#> Failed expectation:
#> add_excitement("goodbye") not identical to "hello!".
#> 1/1 mismatches
#> x[1]: "goodbye!"
#> y[1]: "hello!"
#> Failed expectation:
#> add_excitement("cheers") not identical to "hello!".
#> 1/1 mismatches
#> x[1]: "cheers!"
#> y[1]: "hello!"
#> [[1]]
#> NULL
#> 
#> [[2]]
#> NULL
#> 
#> [[3]]
#> NULL

try(
  purrr::map(
    patterns,~ show_failure(expect_match(add_excitement(!!.),all = TRUE)
    )
  )
)
#> Error in !. : invalid argument type

reprex package (v0.3.0) 于 2021 年 2 月 4 日创建

感谢您的帮助!

解决方法

我能够在 https://r-pkgs.org/tests.html#building-your-own-testing-tools 之后解决这个问题,它使用非标准评估 bquote()eval()(而不是 quasi_label())来产生信息量更大的错误。

library(testthat)
library(purrr)

patterns = c("hello","goodbye","cheers")
add_excitement <- function(pattern) paste0(pattern,"!")

show_failure(eval(bquote(expect_match(add_excitement(.(patterns[2])),"hello!",fixed = TRUE,all = TRUE))))
#> Failed expectation:
#> add_excitement("goodbye") does not match "hello!".
#> Actual value: "goodbye!"


purrr::walk(
  patterns,~ show_failure(eval(bquote(expect_match(add_excitement(.(.)),all = TRUE))))
)
#> Failed expectation:
#> add_excitement("goodbye") does not match "hello!".
#> Actual value: "goodbye!"
#> Failed expectation:
#> add_excitement("cheers") does not match "hello!".
#> Actual value: "cheers!"

reprex package (v0.3.0) 于 2021 年 2 月 4 日创建

或者为了整洁的版本:

library(testthat)
library(purrr)

patterns = c("hello","!")

expect_hello <- function(pattern) {
  show_failure(eval(bquote(expect_match(add_excitement(.(pattern)),all = TRUE))))
}

expect_hello(patterns[2])
#> Failed expectation:
#> add_excitement("goodbye") does not match "hello!".
#> Actual value: "goodbye!"

walk(patterns,expect_hello)
#> Failed expectation:
#> add_excitement("goodbye") does not match "hello!".
#> Actual value: "goodbye!"
#> Failed expectation:
#> add_excitement("cheers") does not match "hello!".
#> Actual value: "cheers!"

reprex package (v0.3.0) 于 2021 年 2 月 4 日创建

,

该错误与 tidyeval bang bang !! operator 的使用有关。
This is superseded,您提供的示例无需 :

show_failure(expect_identical(add_excitement(patterns[2]),"hello!"))

# Failed expectation:
# add_excitement(patterns[2]) not identical to "hello!".
# 1/1 mismatches
# x[1]: "goodbye!"
# y[1]: "hello!"

show_failure(expect_match(add_excitement(patterns[2]),all = TRUE))

# Failed expectation:
# add_excitement(patterns[2]) does not match "hello!".
# Actual value: "goodbye!"

purrr::map(
  patterns,~ show_failure(expect_match(add_excitement(.x),all = TRUE)
  )
)

Failed expectation:
add_excitement(.x) does not match "hello!".
Actual value: "goodbye!"
Failed expectation:
add_excitement(.x) does not match "hello!".
Actual value: "cheers!"
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...