如何测试由“ warnings()”产生的特定警告?

时间:2019-04-30 09:55:55

标签: r tidyverse testthat

问题

我正在使用read_delim函数来读取许多csv文件(非逗号分隔)。由于某些列具有相同的名称,因此会产生警告。我不想编辑原始文件,并且在用read_delim读取列名时无法更改列名。因此,这些警告是不可避免的。但是,我想进行测试,以确保仅生成这些警告,并且没有其他警告,例如错误的列规范等。

我对自己的看法

运行代码后,我可以使用myWarnings <- warnings()捕获警告,但不确定如何对此进行测试。问题是myWarnings是类warnings的列表,我不确定该如何测试。例如myWarnings[[1]]产生NULL,因此我无法测试每个元素。它也不是一个字符向量,而是一个列表。

执行此操作的通常方法是在函数运行时捕获警告。例如testthat::expect_warning(read_delim(...)),但要执行此操作,我将必须运行两次代码:一次用于结果,一次用于测试。我不想这样做,因为这会花费太多时间(而且做事也不是很干净的方式)。

代码

# Pseudocode because you don't have my input files anyway
library(tidyverse)
myInputs <- list.files("myFolder", pattern = ".csv$")
myColTypes <- cols(col1 = col_character(), col2 = col_logical(), etc.)
myData <- map(myInputs, read_delim, delim = "|", col_types = myColTypes)

然后R在控制台中告诉我:There were 36 warnings (use warnings() to see them)。这些警告均显示为:Duplicated column names deduplicated: 'col' => 'col_1' [32], 'col' => 'col_2' [54], 'col' => 'col_3' [211]

我希望能够做这样的事情:

# Again pseudocode, because this is what I would like but it doesn't work.
myWarnings <- warnings()
testthat::expect_equal(
    myWarnings,
    warning("Duplicated column names deduplicated: 'col' => 'col_1' [32], 'col' => 'col_2' [54], 'col' => 'col_3' [211]"
)

1 个答案:

答案 0 :(得分:1)

您可以使用testthat::expect_named()。为什么?从warnings()获得的列表是一个命名列表,其中的名称是警告消息。让我们看一个例子:

for ( i in 1:10 ) {
    x <- log(-i)
}
# Warning messages:
# 1: In log(-i) : NaNs produced
# ...
# 10: In log(-i) : NaNs produced
w <- warnings()
str(w)
# List of 10
#  $ NaNs produced: language log(-i)
#  ...
#  $ NaNs produced: language log(-i)
#  - attr(*, "dots")= list()
#  - attr(*, "class")= chr "warnings"
names(w)
# [1] "NaNs produced" "NaNs produced" "NaNs produced" "NaNs produced"
# [5] "NaNs produced" "NaNs produced" "NaNs produced" "NaNs produced"
# [9] "NaNs produced" "NaNs produced"

然后我们可以使用testthat::expect_named()来测试警告消息是否相等:

testthat::expect_named(w, rep("NaNs produced", 10))