Есть ли в тесте что-то похожее на expect_no_warnings()?

Я пишу тесты для функции, которая при некоторых условиях будет генерировать предупреждения. Я хочу убедиться, что при других условиях он не выдает предупреждений. Я не вижу очевидного способа легко проверить это с помощью testthat. Думаю, я мог бы сделать что-то вроде:

my.result <- 25
my.func <- function() my.result
expect_equal(
  withCallingHandlers(
    my.func(), warning=function() stop("A Warning!")
  ), 
  my.result
)

или используйте options(warn=2), но я надеялся, что будет что-то вроде:

expect_no_warnings(my.func())

Я упускаю что-то очевидное?


person BrodieG    schedule 25.02.2014    source источник
comment
Я делаю это, устанавливая options(warning=2)   -  person Ben Bolker    schedule 25.02.2014
comment
@BenBolker, у меня есть две проблемы с этим подходом: 1. (также проблема с другим предложенным мной альтернативным вариантом), testthat останавливает выполнение при ошибке вместо того, чтобы продолжать и сообщать о любых других неудачных тестах; 2. Я не могу придумать простой систематический механизм отмены этого, который переживет необработанные ошибки в блоке test_that. Обычно я бы сделал on.exit(options(warn=old.warn)), но для этого мне пришлось бы обернуть функцию вокруг блока test_that. Добавление options(warn=old.warn) в конце не приведет к ошибке предупреждения, и мои параметры останутся измененными.   -  person BrodieG    schedule 25.02.2014


Ответы (4)


В еще более поздних версиях «testthat» (начиная с 0.11.0) вы можете:

expect_warning(my.func(), regexp = NA)

Из документации expect_error

regexp: регулярное выражение для проверки. Если опущено, просто утверждает, что код выдает некоторый вывод, сообщение, предупреждение или ошибку. В качестве альтернативы вы можете указать NA, чтобы указать, что не должно быть выходных данных, сообщений, предупреждений или ошибок.

Таким же образом можно проверить отсутствие сообщений, ошибок и вывода.

person alko989    schedule 10.11.2015
comment
В testthat 0.11.0 вы также можете использовать expect_silent(...), если хотите проверить, что он не выдает никаких выходных данных, сообщений или предупреждений за один шаг. - person Stuart R. Jefferys; 29.02.2016
comment
@StuartR.Jefferys, вы правы, если хотите проверить весь вывод. Тем не менее, вопрос в том, как ожидать отсутствия предупреждений. Таким образом, тест, выводящий сообщение, завершится ошибкой, даже если не было выдано никаких предупреждений. - person alko989; 29.02.2016
comment
Абсолютно. Вот почему я добавил его в качестве комментария и перечислил все, что он ловит за один раз. В вопросе не говорилось, что следует перехватывать только предупреждения ;) Я почти всегда использую expect_silent, так как это часто то, что действительно тестируется, и является более строгим. Ваш ответ - лучший способ проверить только предупреждение и разрешить все остальное. - person Stuart R. Jefferys; 29.02.2016
comment
Я не хочу проверять никаких предупреждений, но я получаю вывод. т.е. моя тестируемая функция всегда генерирует предупреждение. Иногда выдает предупреждение. Я хотел бы два тестовых случая. Один для предупреждения и один для вывода, но без предупреждения. - person netskink; 01.09.2017

В последних версиях testthat вы можете просто сделать:

expect_that(my.func(), not(gives_warning()))
person Karl Forner    schedule 26.02.2014
comment
Начиная с testthat 0.10.0 (22 мая 2015 г.) стиль тестов expect_that(A, func(B)) устарел, и в документации not() указано, что он должен быть удален в будущем выпуске. Учитывая это, есть ли другой ответ на этот вопрос, кроме установки options(warning=2)? - person Stuart R. Jefferys; 09.10.2015
comment
Извините, Карл, изменен принятый ответ на alko с учетом устаревания. Подробнее на github. - person BrodieG; 17.03.2016

Обновление: используйте expect_silent() в настоящее время, поскольку expect_that устарело, см. справку по этой функции!.

Обновление 2: Как упоминал @eaglefreeman ответ с использованием expect_warning с параметром regexp, установленным на NA - лучшее решение, поскольку мой ответ приводит к сбою теста, даже если не было выдано никакого предупреждения, а было напечатано только сообщение. Это не то, чего хотел ОП (но просто игнорируйте предупреждения). Я не удаляю этот ответ, чтобы сделать эту разницу понятной для других читателей.

Из примеров справки:

expect_silent("123")

f <- function() {
  message("Hi!")
  warning("Hey!!")
  print("OY!!!")
}

expect_silent(f())

Предупреждение: expect_silent также не ожидает вывода, поэтому семантика немного отличается!

person R Yoda    schedule 13.11.2016
comment
Спасибо, так как это немного более общий вопрос, я оставляю принятый в настоящее время ответ как принятый (например, я могу разрешить стандартный вывод, но не предупреждения, например), но, тем не менее, это полезно знать (+1) - person BrodieG; 14.11.2016
comment
Я должен был понизить это, извините. В данном случае expect_silent на самом деле вводит в заблуждение. - person eaglefreeman; 28.03.2017
comment
@eaglefreeman Можете ли вы уточнить это, пожалуйста, и предложить лучший ответ, чтобы помочь всем нам улучшить это? - person R Yoda; 29.03.2017
comment
Я использовал expect_silent и несколько раз терялся, пытаясь понять, почему это не сработало. Я не хочу, чтобы другие люди экспериментировали с тем же самым :) Лучший ответ — expect_warning с регулярным выражением, установленным на NA. - person eaglefreeman; 30.03.2017
comment
@eaglefreeman Большое спасибо за объяснение, вы абсолютно правы! Я обновил свой ответ, чтобы предупредить других читателей (вместо того, чтобы удалить его). - person R Yoda; 31.03.2017

Вы можете проверить, не работает ли expect_warning(). Следующее решает проблему другого вида вывода, создаваемого my.func() и not(), устаревающим:

expect_failure(expect_warning(my.func()))
person Francesco Napolitano    schedule 21.09.2017