Una de las pocas cosas en las que la mayoría de los desarrolladores de software están de acuerdo es que no debe confiar en que el código funcione correctamente a menos que lo pruebe. Si no lo prueba, puede tener errores ocultos que solo le causarán más trabajo en el futuro.
Entiendo cómo probar mi código normal, pero ¿cómo debo probar mi código de prueba para asegurarme de que pueda encontrar e informar errores de manera efectiva cuando estén presentes? Personalmente, he sido lo suficientemente estúpido como para escribir casos de prueba erróneos que pasarían cuando no deberían hacerlo, lo que en primer lugar anula el propósito de mis pruebas de escritura. Afortunadamente, encontré y arreglé los errores a tiempo, pero según el mantra de pruebas, parece que ningún conjunto de pruebas estaría completo sin tener su propio conjunto de pruebas para asegurarse de que funcionó.
Me parece que la mejor manera de hacer esto sería asegurarme de que la prueba falla para el código defectuoso. * Si paso 2 minutos alternando agregando errores al código y asegurándome de que falla, debería tener un grado aceptable de confianza de que las pruebas 'funcionan'. Esto me lleva a mi segunda pregunta: ¿Cuáles son buenas maneras de introducir errores para asegurarse de que los casos de prueba los atrapen? Debo comentar al azar las declaraciones, asegurarme de que if-else
se ejecuta la rama incorrecta de una negando su condición y cambiar el orden de ejecución del código con efectos secundarios, etc., hasta que esté satisfecho de que mis pruebas atraparán máserrores comunes? ¿Cómo validan los desarrolladores profesionales que sus pruebas realmente hacen lo que se supone que deben hacer? ¿Asumen que las pruebas funcionan o también se toman el tiempo para evaluarlas? Si es así, ¿cómo prueban las pruebas?
No estoy sugiriendo que las personas pasen tanto tiempo probando sus pruebas y luego probando las pruebas para sus pruebas que en realidad nunca escriben el código real, pero he hecho cosas lo suficientemente estúpidas como para sentir que podría beneficiarme un poco de 'meta-pruebas', y tenía curiosidad sobre la mejor manera de hacerlo. :RE
* Podría verificar si la prueba pasa al probar el código 'libre de errores', pero usar el código como una especificación para la prueba parece bastante al revés ...
fuente
Respuestas:
El flujo estándar para TDD es:
La prueba para sus pruebas en este caso es el paso 1: asegúrese de que la prueba falla antes de realizar cambios en el código.
Otra prueba que me gusta es si puede eliminar algún código y volver a implementarlo de una manera diferente, y sus pruebas fallan después de la eliminación, pero funcionan con un algoritmo diferente.
Como con todas las cosas, no hay una bala mágica. Olvidar escribir una prueba requerida es tan fácil para un desarrollador como olvidar escribir el código. Al menos si estás haciendo ambas cosas, tienes el doble de oportunidades para descubrir tu omisión.
fuente
null
y falla en el paso 1. Realiza el cambio de código más pequeño que lo hace pasar al devolver una lista vacía. La prueba ahora es "verde" porque tiene dos errores.null
y no estoy vacío.)Un enfoque es la prueba de mutación , utilizando una herramienta como Jester :
fuente
¿Pruebas para pruebas? No te vayas por ese camino. Entonces probablemente necesitará exámenes para exámenes para exámenes, y luego exámenes para exámenes para exámenes para exámenes ... ¿dónde se detiene?
El flujo de prueba habitual es así, y como desarrollador, pasará la mayor parte de su tiempo en los puntos 1-3:
Su código eventualmente "desarrollará" sus propios errores, no pierda el tiempo introduciéndolos a mano. Sin mencionar, ¿es algo que sabías por adelantado realmente un error? Los errores vendrán, no me preocuparía por eso.
Este es realmente un enfoque viable para verificar si realmente prueba lo que cree que hace. No creo que siempre sea tan bueno, ya que sufre el mismo problema que "prueba por prueba por prueba ...": ¿cuándo deja de alterar el código sabiendo que el código que está probando funciona al 100%?
También es bueno recordar los consejos clásicos de programación pragmáticos de todos los tiempos: no los necesitará . Sé ágil, escribe pruebas y codifica errores reales, en lugar de aquellos hipotéticos que pueden aparecer o no.
fuente
Por construcción, el código funcional y el código de prueba se prueban uno contra el otro. Queda un problema: el caso de los errores de modo común, cuando un error en el código funcional está oculto por un error en el código de prueba. TDD no es inmune a este efecto. Esta es la razón por la cual las pruebas generalmente se realizan en múltiples niveles por diferentes personas para disminuir esta probabilidad.
fuente
Usted prueba su unidad de prueba una vez cuando la escribe, en el depurador. Luego lo dejas solo y te olvidas de eso. No hay ningún problema aquí.
Considera esto. ¿Cuál es el propósito de una prueba unitaria? Te notifica cuando alguno de los numerosos cambios que harás en tu programa principal cambia accidentalmente la lógica en ese programa. Desea tener eso porque sabe que cualquier cambio potencialmente rompe algo. Es por eso que no hay ningún problema si no prueba su prueba: no se mete con su prueba hasta que cambie deliberadamente la lógica de su programa (lo que requeriría que revise la prueba y la pruebe una vez más), por lo que su No es probable que la prueba se rompa accidentalmente.
fuente
Hay una prueba de mutación que evalúa y mide la idoneidad y la calidad de la prueba.
Podemos usar esto para evaluar "la prueba" en sí.
En resumen, podemos evaluar nuestra prueba (por ejemplo, TestA) probando que TestA puede encontrar la diferencia entre el código y sus códigos de mutación (código muy similar pero ligeramente diferente con el código original).
Si TestA no puede encontrar la diferencia entre el código y sus códigos de mutación, significa que TestA tiene regulaciones demasiado estrictas para probar el código original.
fuente