2010-10-14 14 views
11

Pregunta: Estoy probando funciones en un paquete que estoy desarrollando y me gustaría saber si puede sugerir algunas pautas generales sobre cómo hacerlo. Las funciones incluyen una amplia gama de modelos estadísticos, transformaciones, subconjuntos y trazado. ¿Hay una prueba "estándar" o suficiente?directrices para probar una función estadística en R?

Un ejemplo: la prueba que me impulsó esta pregunta,

La función 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)) 
} 

Paso 1: hacer que los datos de prueba:

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

Paso 2: compare la salida esperada de la función con la salida real de la función:

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

Paso 3: tal vez hacer otra prueba

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

Paso 4: si es verdad, considere la función 'funcional'

Respuesta

6

Depende de qué es exactamente lo que quiere probar. Al lado de recomendaciones Dirks, svUnit o el paquete RUnit Vitoshka mencionado, me gustaría añadir un par de cosas:

  • En efecto, establezca la semilla, pero no deje de probar la función con diferentes semillas también. Algunas funciones fallan solo una vez cada diez veces que intentas. Especialmente cuando se trata de optimización, esto se vuelve crucial. replicate() es una buena función para usar en este contexto.
  • Piensa muy bien acerca de la entrada que deseas probar. Debería probar una cantidad de casos "impares" que realmente no se parecen al conjunto de datos "perfecto". Siempre pruebo al menos 10 conjuntos de datos (simulados) de diferentes tamaños.
  • Prueba de la función a prueba de tontos: también incluyo algunos tipos de datos que no son para los que está diseñada la función. La entrada de tipo incorrecto es probable que suceda en un punto, y lo último que desea es una función que devuelva un resultado falso sin una advertencia. Si usa esa función más tarde en algún otro código, ¡la depuración de ese código puede y lo hará! ser el infierno. He estado allí, hecho eso, compré la camiseta ...

Un ejemplo de prueba extendida de conjuntos de datos: ¿qué le gustaría ver como resultado en estos casos? ¿Es este el resultado que esperarías? No según la prueba que hiciste

> 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 

edición: corregido código para pruebas son un poco más senseful.

+1

+1 Joris para la entrada de prueba. Yo agregaría para probar la * salida * también. La salida de sus funciones debe ser * predecible * y * definida con precisión *. Desafortunadamente en este punto, la funcionalidad básica de R a veces solo apesta. Nunca se sabe exactamente a qué devuelve la función a menos que vaya a la documentación de nuevo, y nuevamente, y nuevamente ... – VitoshKa

5

Niza cuestión.

Además de generalidades como establecer una semilla, le recomiendo que vea algunas de las pruebas en las fuentes R. El directorio tests/ en la fuente tiene una gran cantidad de estos; algunos de los paquetes en R Base (como herramientas) también tienen el subdirectorio tests/.

+0

Excelente recurso. Gracias por el puntero. Añadí set.seed() a mi código y seguro que comenzaré a usarlo. ¿Lo usas para análisis o simplemente pruebas y ejemplos? –

+1

Sin una semilla fija no tiene reproducibilidad haciendo comparaciones, depuración, ... un poco más difícil ;-) –

+3

Probablemente ya sepa sobre [runit] (http://cran.r-project.org/web/packages/RUnit /index.html) – VitoshKa

6

tiene que escribir

  1. pruebas que demuestren que obtiene la respuesta correcta cuando se introduce valores razonables

  2. pruebas que muestran su función falla correctamente al sentido de entrada.

  3. prueba para todos los casos de contorno

Hay una gran cantidad de literatura sobre diferentes estrategias para las pruebas de software; Wikipedia software testing page es un buen lugar para empezar.

En cuanto a su ejemplo:

¿Qué pasa cuando se introduce un/trama de datos/lista de cadenas?
¿Qué hay de negativo x o imaginario x?
¿Qué hay de vector/array x?
Si solo está permitido x positivo, ¿qué ocurre en x = 0?

Tenga en cuenta que las subfunciones (que solo son llamadas por sus funciones y nunca por el usuario) necesitan menos comprobación de entrada porque tiene más control sobre lo que entra en la función.

3

Ya apareció como un comentario, pero lo agregaré como una respuesta genuina. R tiene algunos paquetes de prueba automatizados para ayudar con este tipo de cosas, las dos principales son Runit y testthat. He usado brevemente runit, y recientemente comencé a usar testthat con más profundidad (¡sin embargo, no puedo dar buenas ventajas/desventajas de una sobre otra!).

Las pruebas automatizadas le permiten configurar estos casos de prueba, así como otros como se sugirió anteriormente;

  • límite Pruebas de
  • pruebas de tensión (menos necesidad de comprobar la exactitud, sólo tirar de datos en él y ver si se cae)
  • Tratar con entrada diferente
  • Tratar con diferentes plataformas/lugares subyacentes
+1

no se olvide de 'svUnit', parte de sciviews. – mariotomo

Cuestiones relacionadas