2008-11-28 24 views
7

He leído un poco acerca de las pruebas unitarias y me preguntaba cómo probaría USTED. Aparentemente, las pruebas unitarias deben dividir un programa en "unidades" muy pequeñas y probar la funcionalidad desde allí.¿Cómo pruebas tu unidad?

Pero me pregunto, ¿es suficiente para probar la clase por unidad? ¿O lo llevas más allá y los algoritmos de prueba unitarios, fórmulas, etc.? ¿O lo amplía a las páginas/funcionalidades de la prueba de asp? ¿O prueba la unidad en absoluto?

Respuesta

4

Pero me pregunto, ¿es suficiente para probar la clase? ¿O lo llevas más allá y los algoritmos de prueba unitarios, fórmulas, etc.? ¿O lo amplía a las páginas/funcionalidades de la prueba de asp? ¿O prueba la unidad en absoluto?

Un algoritmo debe estar en una clase y automáticamente debe ser probado por la unidad.Una fórmula está dentro de la clase como una función y son unidad probado también. La prueba unitaria prueba el comportamiento, el estado y todas las cosas que se pueden probar para la unidad de desarrollo más pequeña. Entonces, sí, el algoritmo se prueba con todos sus detalles. Más adelante, cuando tenga clases que usen la otra clase, realizará las pruebas de integración (las cuales a menudo se prueban con los programas de Prueba de unidades). Esto será lo mismo pero a un nivel superior.

2

i unit test características, no métodos o clases individuales. La sobrecarga de escribir y mantener pruebas unitarias no es insignificante, y en general no recomiendo escribir pruebas unitarias para cada fragmento de código. Sin embargo, vale la pena probar las funciones de prueba de unidades, porque el cliente le paga por las características.

1

Normalmente programamos en bibliotecas de Java para máquinas. Un programa generalmente está formado por más de veinte bibliotecas, por lo que lo que hacemos es probar la unidad de cada biblioteca. No es una tarea fácil ya que muchas veces las bibliotecas están muy conectadas entre sí y esto no es posible muchas veces.

Nuestro código no es tan modular como quisiéramos, pero debemos aceptarlo por problemas de compatibilidad y romper el acoplamiento significa también romper la compatibilidad en muchos casos.

1

Pruebo la mayor parte de la interfaz pública que puedo (estoy usando C++ pero el lenguaje en realidad no importa). El aspecto más importante es escribir pruebas cuando escribe el código (inmediatamente antes o después). Por experiencia, le aseguro que desarrollar de esta manera conducirá a un código más confiable. y lo hará más fácil de mantener (ya que los cambios que rompan las pruebas serán obviamente inmediatos).

Para todos los proyectos, recomiendo tomar en cuenta las pruebas desde el principio: si escribe una clase que dependa de otra clase complicada, utilice una interfaz para "simular" los objetos más complicados al realizar la prueba (acceso a la base de datos , acceso a la red, etc.).

Escribir un montón de pruebas parecerá desacelerar, pero en realidad, durante la vida útil de un proyecto, pasará menos tiempo solucionando errores.

Pruebe a menudo - si se puede romper, lo hará - y mejor se rompe cuando lo prueba que cuando un cliente está tratando de usarlo.

2

Éstas son las pautas genéricas que encuentro útil para las pruebas unitarias:

1) Identificar objetos de contorno (Win/WebForms, CustomControls etc).

2) Identificar los objetos de control (objetos de la capa de negocios)

3) Asegúrese de escribir Unidad pone a prueba al menos para controlar objetos métodos públicos invocadas por objetos de contorno.

De esta manera estarás seguro de que estás cubriendo los principales aspectos funcionales (características) de tu aplicación y no corres el riesgo de realizar micro-pruebas (a menos que desees).

4

Uso pruebas de unidades como una herramienta para medir si algo funciona o no, después de haber hecho algunos cambios en el código (por ejemplo, refactorizar, corregir un error, agregar una mejora). Como utilizo Java, las pruebas unitarias están en gran parte automatizadas usando JUnit. Solo invoco un script de línea de comando y ejecuta cientos de pruebas para verificar que el código no esté roto.

1

No es suficiente probar la clase solo por unidades. Las clases trabajan juntas, y eso tiene que ser probado también.

hay más unidades que clases:

  • módulos,
  • capas,
  • marcos.

Y existen, por supuesto, diferentes formas de prueba, p. integración y aceptación.

Pruebo las cosas que encuentro difíciles, las cosas que creo que pueden cambiar, las interfaces y las cosas que he tenido que arreglar. Y sobre todo comienzo con la prueba, tratando de asegurarme de entender el problema que estoy tratando de resolver.

2

Soy un tester unitario bastante descuidado, pero luego soy académico, por lo que la mayoría de mis programas son guiones para mi propio uso o programas más pesados ​​para mi investigación. Mucho de mi trabajo es en compiladores, por lo que las pruebas unitarias clásicas son difíciles, por ejemplo, no es tan fácil probar un asignador de registros a menos que tengas un compilador para envolverlo, y en ese punto, también puedes ir a pruebas de regresión.

Pero hay algunas excepciones importantes. Hago una gran cantidad de secuencias de comandos en Lua, que se divide en módulos (un archivo fuente puede ser, y a menudo es un módulo). Si estoy trabajando en cosas nuevas, como las utilidades para interactuar con el shell, simplemente dejaré algunas pruebas de unidad dentro del módulo. donde se ejecutan cada vez que se carga el módulo. Lua es tan rápido que generalmente esto no importa. Aquí hay algunos ejemplos:

 
assert(os.quote [[three]] == [[three]]) 
assert(os.quote [[three"]] == [['three"']]) 
assert(os.quote [[your mama]] == [['your mama']]) 
assert(os.quote [[$i]] == [['$i']]) 

Si soy un buen perro, escribo algunas pruebas simples como estas antes de escribir la función.

La otra cosa que hago con la unidad de pruebas es que si es algo difícil, lo leyes algebraicas prueba usandoQuickCheck, que es una herramienta de prueba al azar que tiene que ser visto para ser creído. Es la única herramienta que he usado y que hace que la prueba de unidades sea divertida. Un enlace está colgando, pero puedes encontrar Tom Moertel's story about the ICFP programming contest en su blog.

Espero que te sea útil. QuickCheck ha guardado mi tocino muchas veces. Más recientemente, probé el código para la transformación del coseno discreto usando una aritmética racional exacta, ¡y luego lo porté a C!

1

¡Solo porque compila no significa que se ejecuta! Esa es la esencia de las pruebas unitarias. Prueba el código.Asegúrate de que está haciendo lo que pensabas que estaba haciendo.

Seamos realistas, si traes una transformación matricial de matlab, es fácil arruinar un signo más o menos en alguna parte. Ese tipo de cosas es difícil de ver. Sin probarlo, simplemente no sabes si funcionará correctamente. Depurar 100 líneas de código es mucho más fácil que depurar 100.000 líneas de código.


Algunas personas toman esto a los extremos. Intentan probar cada cosa concebible. Las pruebas se convierten en un fin en sí mismo.

Esto puede ser útil más adelante durante las fases de mantenimiento. Puede verificar rápidamente para asegurarse de que sus actualizaciones no hayan roto nada.

¡Pero la sobrecarga implicada puede paralizar el desarrollo del producto! Y los cambios futuros que alteran la funcionalidad pueden implicar una gran sobrecarga de actualización de prueba.

(También puede causar problemas con respecto a la multi-threading y orden de ejecución arbitraria.)


En última instancia, a menos que se indique lo contrario, mis pruebas tratan de golpear la tierra de en medio.

Mirar para probar en granularidades más grandes, proporcionando un medio de verificar la funcionalidad general básica. No me preocupo tanto por cada posible escenario de cercado. (Para eso están las macros ASSERT).

Por ejemplo: cuando escribí código para enviar/recibir mensajes por UDP, armé una prueba rápida para enviar/recibir datos usando esa clase a través de la interfaz loopback. Nada sofisticado. Rápido, rápido, & código sucio. Solo quería probarlo. Para asegurarme de que realmente funcionaba antes de construir algo encima.

Otro ejemplo: lectura en las imágenes de la cámara desde una cámara Firewire. Lancé una aplicación GTK & sucia para leer las imágenes, procesarlas y mostrarlas en tiempo real. Otras personas lo llaman prueba de integración. Pero puedo usarlo para verificar mi interfaz Firewire, mi clase de imagen, mi transformación Bayer RGGB-> RGB, mi orientación a la imagen & alineación, incluso si la cámara se volvió a colocar boca abajo. Pruebas más detalladas solo estarían justificadas si esto hubiera resultado insuficiente.

Por otro lado, incluso para algo tan simple como:

template<class TYPE> inline TYPE MIN(const TYPE & x, const TYPE & y) { return x > y ? y : x; } 
template<class TYPE> inline TYPE MAX(const TYPE & x, const TYPE & y) { return x < y ? y : x; } 

me escribió una línea de 1 MOSTRAR macro para asegurarse de que no había ensuciado el signo:

SHOW(MIN(3,4)); SHOW(MAX(3,4)); 

Todos Quería hacer era verificar que estaba haciendo lo que debería estar haciendo en el caso general. Me preocupa menos cómo se maneja NaN/+ -Infinity/(double, int) que si uno de los colegas decidió cambiar el orden de los argumentos y se equivocó.


En cuanto a la herramienta, hay muchas cosas para probar la unidad. Si te ayuda, más poder para ti. Si no, bueno, realmente no necesitas ser demasiado elegante.

menudo voy a escribir un programa de prueba que vuelca datos dentro y fuera de una clase, y luego lo imprime todo lo alto con un espectáculo macro:

#define SHOW(X) std::cout << # X " = " << (X) << std::endl 

(Por otra parte, muchas de mis clases puede auto- imprimir utilizando un operador incorporado < < método (ostream &). es una técnica increíblemente útil para depurar, así como para la prueba!)

Makefile puede ser trivialmente extendido para generar automáticamente archivos de salida de los programas de prueba, y para automáticamente comparar (diff) estos archivos de salida con anterioridad resultados conocidos (revisados).

No es elegante, tal vez un poco menos que elegante, pero a medida que las técnicas van esto es muy efectivo, rápido de implementar y muy bajo. (Lo cual tiene sus ventajas cuando su gerente desaprueba de perder tiempo en esas cosas las pruebas.)


Una última reflexión os dejo con. Esto me va a marcar, así que ¡NO HAGA!

Hace algún tiempo necesitaba un programa de prueba. Era un entregable requerido. El programa en sí tenía que verificar que otra clase funcionaba correctamente. Pero no pudo acceder a los archivos de datos externos. (No podíamos confiar en dónde se ubicaría el programa en relación con cualquier otra cosa. Tampoco en las rutas absolutas). El marco de pruebas unitarias para el proyecto era incompatible con el compilador que debía usar. También tenía que estar en un archivo. El sistema de archivo de proyecto no admite la vinculación de varios archivos para un programa de prueba modesto. (Los programas de aplicación, seguro. Podrían utilizar las bibliotecas. Pero sólo un único archivo para cada programa de prueba.)

Por lo tanto, Dios me perdone, yo "rompió las reglas" ...

< vergüenza >
Utilicé macros. Cuando se definía una macro #define, los datos se escribían en un segundo archivo .c como inicializador para una matriz de estructuras. Posteriormente, cuando el software fue recompilado, y ese segundo archivo .c (con el array struct) fue #incluido, y la macro #define no se configuró, comparó los nuevos resultados con los datos almacenados anteriormente. Sí, incluí un archivo .c. Oh, la vergüenza de todo.
</vergüenza >

Pero se puede hacer ...

Cuestiones relacionadas