unit-testing - telecomunicaciones - tdd pdf
¿Qué debe ser una "unidad" cuando la unidad prueba? (9)
En Proggit, hoy estaba leyendo el hilo de comentarios en una presentación titulada " Por qué la prueba unitaria es una pérdida de tiempo ".
No estoy realmente preocupado por la premisa del artículo tanto como lo estoy con un comment respecto:
La raíz del problema es que la mayoría de las "unidades" de código en los proyectos de software empresarial son triviales.
¿Cambiar el tamaño de la unidad hasta que deje de ser trivial? ¿Quién demonios definió la unidad de código como una sola función o método de todos modos?
y
Bueno, algunos de los tipos con los que trabajé querían definir una unidad como funciones individuales. Fue completamente estúpido. Mi definición favorita de "unidad" es: la parte más pequeña del código que puede probarse de manera útil.
¿Pasamos demasiado tiempo solo para burlarnos de algunos objetos y probar una pieza trivial de código y realmente no estamos agregando nada de valor?
¿Qué debe ser una "unidad" cuando la Unidad de Pruebas? ¿Las pruebas de nivel de función son demasiado granulares?
¿Cambiar el tamaño de la unidad hasta que deje de ser trivial? ¿Quién demonios definió la unidad de código como una sola función o método de todos modos?
Si es demasiado difícil probar una "unidad" definida como un método, entonces es probable que el método sea demasiado grande o complicado para realizar una prueba de unidad.
Sigo una metodología similar sugerida por rwmnau y realizo pruebas a nivel de método. Además de crear una prueba por método, creo pruebas adicionales para las diferentes rutas de código en cada método. A veces, acentuar todas las rutas de código puede complicarse. Mi desafío es tratar de evitar escribir los tipos de métodos a menos que no haya una mejor solución en términos de rendimiento y complejidad de código.
También uso simulacros para probar contratos entre componentes.
En general, cuanto más pequeñas sean sus unidades, más útiles y efectivas serán sus pruebas unitarias. El punto principal de las pruebas de unidades es poder localizar cualquier error recién introducido en una pequeña parte del código.
Nada es trivial, si se tiene en cuenta la Ley de Murphy.
Haciendo bromas y asumiendo un entorno OO, me acerco a las Pruebas unitarias tomando una clase como la unidad, porque a menudo los diversos métodos modifican el estado interno y quiero estar seguro de que el estado entre los distintos métodos es consistente.
Desafortunadamente, a menudo la única forma de verificar la consistencia es invocar varios métodos de una clase para ver si fallan o no.
Para mí, una "unidad" es cualquier comportamiento significativo de una clase que, en 8-12 meses, no voy a recordar.
Y con las pruebas de unidad bien escritas (creo que BDD ), no tendré que hacerlo, porque mi prueba me describirá y verificará el código en un lenguaje sencillo.
Puede parecer trivial citar a Wikipedia , pero creo que es muy breve y preciso en este caso:
Una unidad es la parte comprobable más pequeña de una aplicación.
Esto parece estar de acuerdo con el comentario en su pregunta de que una unidad es "la pieza más pequeña del código que puede probarse de manera útil". En otras palabras, haga que la unidad sea lo más pequeña posible, de modo que aún tenga sentido para el desarrollador / probador por sí mismo .
A menudo, deseará probar partes de un proyecto de forma aislada y luego probar cómo interactúan en combinación. Tener varios niveles (niveles) de pruebas de unidad a menudo es una buena idea, ya que ayuda a asegurar que su código funcione como debería en todos los niveles, desde funciones individuales hasta tareas completas e independientes. Personalmente, no creo que sea incorrecto, o incluso que no sea útil, probar las funciones individuales, siempre y cuando estén haciendo algo útil en sí mismos, lo que a menudo puede ser el caso.
Para ser honesto, no hay una definición definida o rigurosa de una "unidad" en "prueba de unidad", por lo que precisamente se usa el vago término "unidad". Aprender lo que se necesita probar y en qué nivel es cuestión de experiencia, y muy a menudo, simplemente prueba y error. Puede sonar como una respuesta un tanto insatisfactoria, pero creo que es una buena regla a seguir.
Siempre he probado en el nivel de función, y eso ha funcionado bien. El gran punto para mí es que las pruebas unitarias prueban el contrato entre dos piezas de código. La prueba de la unidad solo actúa como un llamador y garantiza que el código que se está probando (sin importar qué tan grande sea una función o una biblioteca enorme y anidada que demore 30 minutos en realizar la prueba) arroja resultados de una manera predecible.
El punto completo de una unidad lo prueba para asegurar la compatibilidad (no rompiendo las interacciones) y asegurar resultados predecibles. Las pruebas en cualquier lugar donde haya un intercambio de información ayudarán a estabilizar su aplicación.
ACTUALIZACIÓN: También siempre he agregado una prueba de unidad cada vez que un cliente o usuario informa un caso de ventaja que rompe una interacción en mi aplicación. Arreglarlo no es suficiente para mí: agregar una prueba de unidad para garantizar que la corrección se mantenga previene la regresión y ayuda a mantener las cosas estables en el futuro.
Sospecho que "prueba de unidad" es un término mal utilizado. Hoy en día, el término no solo se usa para referirse a probar un pequeño fragmento de código, sino que se usa para cualquier prueba que sea automatizada.
Tiendo a escribir mis pruebas antes de escribir mi código, así que no puedo decirte cuándo lo escribo por primera vez si va a causar la creación de algunas líneas nuevas, un método nuevo o una clase nueva.
Entonces, en una palabra: mu .
Una "unidad" debe ser una sola unidad atómica para su definición . Es decir, precisamente lo que define una "unidad" para la prueba unitaria es bastante subjetivo; Puede depender bastante de qué es exactamente su arquitectura y de cómo su aplicación elige desglosar las unidades funcionales. Lo que estoy diciendo es que no hay una "unidad" claramente definida, excepto por lo que usted define. Una "unidad" puede ser un método único que tiene un único efecto secundario, o puede ser un conjunto relacionado de métodos que juntos definen un conjunto único y coherente de funcionalidad.
La racionalidad es bastante importante aquí; es totalmente posible escribir pruebas unitarias para cada descriptor de acceso de cada clase que tenga; Sin embargo, eso es claramente una exageración. De manera similar, es posible, pero tonto, definir toda la aplicación como una unidad y esperar tener una sola prueba para probarla.
En general, usted desea una "unidad" para la prueba que describa una porción de funcionalidad claramente definida y claramente distinta. En cada nivel de visualización de su aplicación, debería poder ver "átomos" claros de funcionalidad (si su diseño es bueno); estos pueden ser tan simples como "recuperar un registro de la base de datos" para una vista de bajo nivel, y tan complicados como "crear, editar y eliminar un usuario" en una vista de alto nivel. Tampoco son mutuamente excluyentes; Fácilmente puede tener ambos como pruebas unitarias.
El punto que debe tomarse aquí es que la unidad que desea probar es la unidad que tiene sentido. Desea que la prueba unitaria valide y verifique la funcionalidad; así que lo que una prueba de prueba es lo que define como funcionalidad. ¿Qué es una unidad de funcionalidad? Eso depende de su situación individual para definir.
Yo diría que una unidad es la porción significativa más pequeña de trabajo que se puede separar de otros pasos en pseudocódigo.
Por ejemplo, si está intentando realizar una serie de pasos para procesar algunos datos, como
- escanear el conjunto de datos para el mínimo, máximo, mediana, media
- generar un histograma
- generar una función de reasignación
- reasignar los datos
- sacar los datos
Cada uno de esos pasos sería una ''unidad'', y toda la serie también es una ''unidad'' (para probar que la cohesión entre cada uno de ellos funciona). Cualquiera de estos pasos podría ser cuatro funciones (para el primer paso, si el programador está ejecutando cuatro bucles), o una función, o lo que sea, pero al final, las entradas conocidas deben proporcionar salidas conocidas.