Probamos nuestro código para hacerlo más correcto (en realidad, es menos probable que sea incorrecto ). Sin embargo, las pruebas también son código, también pueden contener errores. Y si sus pruebas son defectuosas, difícilmente mejorarán su código.
Puedo pensar en tres posibles tipos de errores en las pruebas:
Errores lógicos, cuando el programador malinterpretó la tarea en cuestión y las pruebas hacen lo que él pensó que deberían hacer, lo cual está mal;
Errores en el marco de prueba subyacente (por ejemplo, una abstracción burlona permeable);
Errores en las pruebas: la prueba está haciendo un poco diferente de lo que el programador cree que es.
Los errores de tipo (1) parecen ser imposibles de evitar (a menos que el programador solo ... se vuelva más inteligente). Sin embargo, (2) y (3) pueden ser manejables. ¿Cómo manejas este tipo de errores? ¿Tienes alguna estrategia especial para evitarlos? Por ejemplo, ¿escribe algunas pruebas especiales "vacías", que solo verifican las presuposiciones del autor de la prueba? Además, ¿cómo aborda la depuración de un caso de prueba roto?
fuente
Respuestas:
Las pruebas ya están probadas. Las pruebas están protegidas por diseño de los errores, porque las pruebas solo detectan diferencias entre el código y nuestras expectativas. Si hay problemas tenemos un error. El error podría estar en el código o con la misma probabilidad en las pruebas.
Existen algunas técnicas que le impiden agregar el mismo error tanto en el código como en las pruebas:
No necesita probar la plataforma subyacente. Las pruebas no solo ejercitan el código escrito por usted, sino que también ejecutan el código desde la plataforma. Si bien no necesariamente desea detectar errores en la plataforma de prueba, es muy difícil escribir código y pruebas que siempre oculten un error en la plataforma, en otras palabras, es muy difícil tener un error sistemático tanto en sus pruebas / código como en en la plataforma, y la probabilidad se reduce con cada prueba que cree. Incluso si intentaras hacer esto, tendrías una tarea muy difícil.
Podría tener errores en las pruebas, pero generalmente se detectan fácilmente porque el código desarrollado prueba las pruebas. Entre el código y las pruebas tiene una retroalimentación de auto aplicación. Ambos predicen cómo debería comportarse una llamada específica de una interfaz. Si la respuesta es diferente, no necesariamente tiene un error en el código. También podría tener un error en la prueba.
fuente
Intente hacer que las pruebas individuales sean lo más pequeñas (cortas) posible.
Esto debería reducir las posibilidades de crear un error en primer lugar. Incluso si logras crear uno, es más fácil de encontrar. Se supone que las pruebas unitarias son pequeñas y específicas, con baja tolerancia a fallas y desviaciones.
Al final, probablemente sea solo una cuestión de experiencia. Cuantas más pruebas escriba, mejor lo hará, menos posibilidades tendrá de hacer pruebas desagradables.
fuente
A
, espera resultadosB
. Si no tiene estadoA
, una prueba debería fallar. En ese momento, puede investigar por qué falló, malas condiciones iniciales o una mala prueba, pero debería fallar en ambos casos. Incluso si lo es, como usted dice, "ligeramente fuera" (es decir"A" => "B"
,"a" => "b"
, pero nunca"a" => "B"
o su prueba es malo).Una táctica es escribir la prueba antes del código que prueba, y asegurarse de que la prueba falla primero por la razón correcta. Si usa TDD , debe obtener al menos este nivel de prueba de pruebas.
Una forma más exhaustiva de probar la calidad de un conjunto de pruebas es utilizar pruebas de mutación .
fuente
Para el n. ° 1 y n. ° 3: las pruebas unitarias no deben contener ninguna lógica; si lo hace, probablemente esté probando más de una cosa en su prueba unitaria. Una práctica recomendada para las pruebas unitarias es tener solo una prueba por prueba unitaria.
Mire este video de Roy Osherove para obtener más información sobre cómo escribir bien las pruebas unitarias.
fuente
En términos de # 1: creo que es una buena idea emparejar / revisar el código para este lado de las cosas. Es fácil hacer presuposiciones o simplemente equivocarse, pero si tiene que explicar lo que está haciendo su prueba, cuál es el punto, es más probable que responda si apunta al objetivo equivocado.
fuente
Debe haber un punto en el que uno debe dejar de intentar la prueba unitaria. Debe saber cuándo dibujar la línea. ¿Deberíamos escribir casos de prueba para probar casos de prueba? ¿Qué pasa con los nuevos casos de prueba escritos para probar los casos de prueba? ¿Cómo los probaremos?
Editar: actualizado con la explicación sugerida por el comentario.
fuente
Oye.
Tienes que las aplicaciones:
Cuando ejecuta pruebas contra su producto, en realidad no está interesado en la prueba en sí, sino en la interacción entre su producto y sus pruebas. Si la prueba falla, no dice que la aplicación tenga un error. Dice que la interacción entre el producto y la prueba no fue exitosa . Ahora es su trabajo determinar qué salió mal. Puede ser:
Para mí, las pruebas que fallan no son simples comentarios, que esto y aquello está mal . Es un indicador de que hay inconsistencia, y necesito examinar ambos para verificar que el error salió mal. Al final, soy responsable de verificar que la aplicación sea correcta, las pruebas son solo una herramienta para resaltar áreas que vale la pena verificar.
Las pruebas solo verifican algunas partes de la aplicación. Pruebo la aplicación, pruebo las pruebas.
fuente
Las pruebas no deberían ser lo suficientemente "inteligentes" como para albergar errores.
El código que está escribiendo implementa un conjunto de especificaciones. (Si X entonces Y, a menos que Z en cuyo caso Q, etc., etc.). Todo lo que la prueba debe intentar lograr es determinar que X realmente es Y a menos que Z, en cuyo caso Q. Esto significa que todo lo que debe hacer una prueba es establecer X y verificar Y.
Pero eso no cubre todos los casos, probablemente esté diciendo, y tendría razón. Pero si hace que la prueba sea lo suficientemente "inteligente" como para saber que X solo debe ser Y si no Z, entonces básicamente está re-implementando la lógica de negocios en la prueba. Esto es problemático por razones que profundizaremos un poco más abajo. No debería mejorar la cobertura del código al hacer que su primera prueba sea "más inteligente", sino que debe agregar una segunda prueba tonta que establezca X y Z y verifique Q. De esa manera tendrá dos pruebas, una que cubre el caso general ( a veces también conocido como el camino feliz) y uno que cubre el caso límite como una prueba separada.
Hay varias razones para esto, en primer lugar, ¿cómo se determina si una prueba fallida se debe a un error en la lógica de negocios o un error en las pruebas? Obviamente, la respuesta es que si las pruebas son lo más simples posible, es muy poco probable que alberguen errores. Si crees que tus pruebas necesitan pruebas, entonces estás probando mal .
Otras razones incluyen que solo está replicando el esfuerzo (como ya mencioné, escribir una prueba lo suficientemente inteligente como para ejercer todas las posibilidades en una sola prueba es básicamente replicar la lógica de negocios que está tratando de probar en primer lugar), si los requisitos cambian entonces las pruebas deberían ser fáciles de cambiar para reflejar los nuevos requisitos, las pruebas sirven como una especie de documentación (son una forma formal de decir cuál es la especificación de la unidad bajo prueba), y así sucesivamente.
TL: DR: Si sus pruebas necesitan pruebas, lo está haciendo mal. Escribe pruebas tontas .
fuente
No es una respuesta (no tengo el privilegio de comentar), pero me preguntaba si olvidó otras razones para desarrollar casos de prueba ...
Una vez que descubra todos los errores en las pruebas, puede probar su aplicación fácilmente. Las suites de prueba automatizadas lo ayudarán a encontrar problemas antes, antes de la integración. Los cambios en los requisitos son relativamente más fáciles de probar, ya que los cambios pueden convertirse en una versión más nueva y alterada de los casos de prueba más antiguos que pasan y los casos más antiguos permanecen para detectar fallas.
fuente
Respuesta corta: el código de producción prueba las pruebas .
Compare esto con el modelo de crédito / débito utilizado en economía. La mecánica es muy simple: si el crédito difiere del débito, hay algo mal.
Lo mismo ocurre con las pruebas unitarias: si una prueba falla, indica que algo está mal. Puede ser el código de producción, ¡pero también puede ser el código de prueba! Esta última parte si es importante.
Tenga en cuenta que sus errores tipo (1) no se pueden encontrar mediante pruebas unitarias. Para evitar este tipo de errores, necesita otras herramientas.
fuente