Руководство по тестированию статистической функции в R? - PullRequest
11 голосов
/ 15 октября 2010

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

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

Функция 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's 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, считать функцию «функциональной»

Ответы [ 4 ]

6 голосов
/ 15 октября 2010

Это зависит от того, что именно вы хотите проверить.Наряду с рекомендациями Диркса, 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: исправлен код, поэтому тесты немного более понятны.

6 голосов
/ 15 октября 2010

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

  1. тестов, которые показывают, что вы получаете правильный ответ при вводе разумных значений

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

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

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

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

Что происходит, когда вы вводите строку / фрейм данных / список?
А как насчет отрицательного x или мнимого x?
Как насчет вектора / массива x?
Если разрешен только положительный x, то что происходит в x = 0?

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

5 голосов
/ 15 октября 2010

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

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

3 голосов
/ 15 октября 2010

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

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

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