Рекомендации по тестированию статистической функции в 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 более подробно (я не могу дать никаких хороших преимуществ/недостатков одного над другим, хотя!).
Автоматическое тестирование позволяет вам настроить эти тестовые примеры, а также другие, как было предложено выше:
- Граничные тесты
- Тесты стресса (меньше нужно проверять точность, просто бросать на него данные и видеть, падает ли он)
- Работа с разными входами
- Работа с различными базовыми платформами/локалями