Рекомендации по тестированию статистической функции в R?

Вопрос: Я тестирую функции в пакете, который я разрабатываю, и хотел бы знать, можете ли вы предложить некоторые общие рекомендации относительно того, как это сделать. Эти функции включают в себя широкий спектр статистического моделирования, преобразований, подмножества и построения графиков. Есть ли "стандартный" или достаточный тест?

Пример: тест, который побудил меня задать этот вопрос,

Функция dtheta:

dtheta <- function(x) {
  ## find the quantile of the mean
  q.mean <- mean(mean(x) >= x)
  ## find the quantiles of ucl and lcl (q.mean +/- 0.15)
  q.ucl  <- q.mean + 0.15
  q.lcl  <- q.mean - 0.15
  qs <- c(q.lcl, q.mean, q.ucl)
  ## find the lcl, mean, and ucl of the vector
  c(quantile(x,qs), var(x), sqrt(var(x))/mean(x))
}

Шаг 1: выполните тестовые данные:

set.seed(100) # per Dirk recommendation
test <- rnorm(100000,10,1)

Шаг 2: сравните ожидаемый результат функции с фактическим выходом функции:

 expected <- quantile(test, c(0.35, 0.65, 0.5))
 actual   <- dtheta(test)[1:3]
 signif(expected,2) %in% signif(actual,2)

Шаг 3: возможно, выполните еще один тест

test2 <- runif(100000, 0, 100)
expected <- c(35, 50, 65)
actual   <- dtheta(test2)
expected %in% signif(actual,2)

Шаг 4: если true, рассмотрим функцию "функционал"

Ответ 1

Это зависит от того, что именно вы хотите проверить. Рядом с рекомендациями Dirks, svUnit или пакет RUnit VitoshKa, я хотел бы добавить несколько вещей:

  • В самом деле, установите семя, но убедитесь, что вы попробуете функцию с разными семенами. Некоторые функции срабатывают только один раз каждые десять раз. Особенно, когда речь идет о оптимизации, это становится решающим. replicate() - хорошая функция для использования в этом контексте.
  • Подумайте о том, какой вход вы хотите протестировать. Вы должны проверить несколько "странных" случаев, которые на самом деле не похожи на "идеальный" набор данных. Я всегда тестирую по меньшей мере 10 (имитируемых) наборов данных разных размеров.
  • Неверная функция: я также использую некоторые типы данных, которые не предназначены для функции. Неправильный ввод типа, вероятно, произойдет в какой-то момент, и последнее, что вы хотите, - это функция, возвращающая фиктивный результат без предупреждения. Если вы позже используете эту функцию в другом коде, отладка этого кода может и будет! будь ад. Был там, сделал это, купил футболку...

Пример расширенного тестирования наборов данных: что бы вы хотели видеть в качестве вывода в этих случаях? Это результат, которого вы ожидаете? Не в соответствии с тестом, который вы сделали.

> test3 <- rep(12,100000) # data with only 1 value
> expected <- c(12, 12, 12)
> actual   <- dtheta(test3) 
Error in quantile.default(x, qs) : 'probs' outside [0,1]

>  test4 <- rbinom(100000,30,0.5) # large dataset with a limited amount of values
>  expected <- quantile(test4,c(0.35, 0.50, 0.65))
>  actual   <- dtheta(test4)
>  expected %in% signif(actual,2)
[1] FALSE  TRUE  TRUE

> test5 <- runif(100,0,100) # small dataset. 
> expected <- c(35, 50, 65)
> actual   <- dtheta(test5)
> expected %in% signif(actual,2)
[1] FALSE FALSE FALSE

edit: исправленный код, поэтому тесты немного более понятны.

Ответ 2

Вам нужно написать

  • которые показывают, что вы получаете правильный ответ, когда вводите разумные значения

  • тесты, которые показывают, что ваша функция работает неправильно, когда вы вводите бессмыслицу.

  • тест для всех граничных случаев

Существует огромное количество литературы по различным стратегиям тестирования программного обеспечения; Wikipedia страница тестирования программного обеспечения - это то место, которое нужно начинать.

Глядя на ваш пример:

Что происходит, когда вы вводите строку /dataframe/list?
Что относительно отрицательного x или мнимого x?
Как насчет vector/array x?
Если допустимо только положительное x, то что происходит при x = 0?

Обратите внимание, что подфункции (которые вызываются только вашими функциями и никогда не пользователь) требуют меньше проверки ввода, потому что у вас больше контроля над тем, что входит в функцию.

Ответ 3

Хороший вопрос.

Помимо общих особенностей, таких как установка семени, я бы рекомендовал вам изучить некоторые из тестов в источниках R. Каталог tests/ в источнике имеет множество таких; некоторые из пакетов в базе R (например, инструменты) также имеют подкаталог tests/.

Ответ 4

Он уже появился в качестве комментария, но я добавлю его в качестве добросовестного ответа. У R есть несколько автоматических пакетов тестирования, которые помогут в этом, главные из них: Runit и testthat. Я кратко использовал runit, и в последнее время начал использовать testthat более подробно (я не могу дать никаких хороших преимуществ/недостатков одного над другим, хотя!).

Автоматическое тестирование позволяет вам настроить эти тестовые примеры, а также другие, как было предложено выше:

  • Граничные тесты
  • Тесты стресса (меньше нужно проверять точность, просто бросать на него данные и видеть, падает ли он)
  • Работа с разными входами
  • Работа с различными базовыми платформами/локалями