【问题标题】:{testthat} `quasi_label` with `expect_match` throws "Error: invalid argument type"{testthat} `quasi_label` 和 `expect_match` 抛出“错误:参数类型无效”
【发布时间】:2021-05-08 17:41:07
【问题描述】:

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

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

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

  • 为什么expect_identical 而不是expect_match 接受quasi_label 参数?
  • 我是否可以使用 expect_identical 而不是 expect_match 来实现我的目的,或者这会带来其他错误的风险吗?

这是一个代表:

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(!!.), "hello!", 
                                fixed = TRUE, all = TRUE)
    )
  )
)
#> Error in !. : invalid argument type

reprex package (v0.3.0) 于 2021-02-04 创建

感谢您的帮助!

【问题讨论】:

    标签: r rlang testthat quasiquotes


    【解决方案1】:

    我能够在 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(.(.)), "hello!", fixed = TRUE, 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", "goodbye", "cheers")
    add_excitement <- function(pattern) paste0(pattern, "!")
    
    expect_hello <- function(pattern) {
      show_failure(eval(bquote(expect_match(add_excitement(.(pattern)), "hello!", fixed = TRUE, 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-02-04 创建

    【讨论】:

      【解决方案2】:

      该错误与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]), "hello!", fixed = TRUE,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), "hello!", 
                                    fixed = TRUE, 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
      

      【讨论】:

      • 谢谢。但是,没有tidyeval 的版本不会在错误中显示patternshow_failure(expect_identical(add_excitement(!!patterns[2]), "hello!")) 提供add_excitement("goodbye") not identical to "hello!".show_failure(expect_identical(add_excitement(patterns[2]), "hello!")) 提供的信息较少add_excitement(patterns[2]) not identical to "hello!".
      • 感谢您的反馈,很高兴您找到了解决方案!
      猜你喜欢
      • 2019-01-25
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 2023-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多