¿Deberían eliminarse las pruebas unitarias que fallan que no vamos a corregir? [duplicar]

13

A mi compañero de trabajo le gusta que pasen todas nuestras pruebas de unidad (como lo haría cualquiera) y argumenta que algunas de las pruebas fallidas de un sistema que escribió no son "ruido" innecesario, ya que todas involucran la validez de los datos y una Se supone que el sistema en nuestra pila es responsable de la validación.

Personalmente, creo que mantener las pruebas le permite, al menos, comprender / reconocer algunos de los puntos que fallan, incluso si conscientemente elige no solucionarlos.

¿Tiene razón al querer que se eliminen, ya que son "ruido" en comparación con la otra funcionalidad probada y probablemente nunca se solucionarán?

Solo por contexto. Aquí hay algunos ejemplos concretos. Todos implican rutas de código que se utilizan, pero pasar datos no validados a las rutinas provoca comportamientos inesperados:

  • pasar en NaN da como resultado un falso positivo.
  • pasar un valor que desborda las cifras significativas de un doble da como resultado false cuando debería haberse devuelto true. El redondeo no debe ocurrir.
    • "139.9999999999999" - > Double.TryParse () - > 139.9999999999999
    • "139.99999999999999" - > Double.TryParse () - > 140
pregunta Brandon Boone 02.05.2014 - 22:17

9 respuestas

23

Permítanme comenzar con algunas aserciones:

  • Las pruebas se utilizan para mostrarle dónde falla su código.
  • Las pruebas deben cubrir todos los escenarios para cada unidad que desee probar.
  • Los resultados de la prueba deben proporcionar una visión general clara de lo que salió mal.

Ahora en tu escenario: reconoces que estas pruebas están escritas en una ubicación a la que no pertenecen. Supongo que a partir de su historia, usted tiene un proyecto separado que prueba toda la validación, ¿por qué no simplemente transfiere estas pruebas a ese proyecto?

Las desventajas de mantener estas pruebas donde no pertenecen:

  • Las pruebas se fracturan en todos los proyectos a pesar de que tienen un lugar designado para mantenerlos juntos.
  • La información general sobre qué pruebas fallidas son relevantes y cuáles se ignoran conscientemente se hace más difícil y es posible que se pierda algunas pruebas de ruptura nuevas.

Dicho esto: eliminar las pruebas solo porque desea verlas pasar, no es ni la respuesta. Obviamente, la solución preferida es solucionarlos, pero cuando esto no sea posible, es posible que desee clasificarlos dentro de un proyecto separado.

También se debe tener en cuenta que las pruebas duplicadas tampoco son buenas. Si tiene dos pruebas en dos proyectos diferentes que prueban exactamente lo mismo, entonces tiene que realizar el mantenimiento de dos, mientras que solo se beneficia de una. Si prueba su validación en el proyecto ValidationTest y hace lo mismo en su otro proyecto, debe eliminarlos de su otro proyecto y mantener las cosas contenidas donde se supone que deben estar.

Por último, es posible que también desee hacer uso de las posibilidades del marco de prueba. Por ejemplo, MSTest le permitirá agregar un atributo [Ignore] a las pruebas que deben ignorarse. Esto dará como resultado una buena barra verde con una categoría adicional de pruebas ignoradas, manteniéndolas prevalentes.

    
respondido por el Jeroen Vannevel 02.05.2014 - 22:39
7

Depende ...

Si las pruebas que fallan pertenecen a una funcionalidad que no se está eliminando, entonces no se deben eliminar.

Como probablemente sepa, todo el punto de las pruebas unitarias debe ser capaz de probar de forma rápida y rápida todas las partes y partes pequeñas de su código en un nivel micro para determinar que cada componente pequeño está haciendo lo que se supone que debe hacer. Si un componente todavía está en uso, debería tener una prueba ...

La siguiente pregunta es ¿por qué están fallando? ¿Deberían trasladarse las pruebas a un lugar más apropiado para las pruebas? ¿Hubo un cambio en el diseño del sistema que los rompió? ¿Las pruebas no se diseñaron correctamente y están fallando debido a eso?

Independientemente del problema. Si la funcionalidad aún existe, deben permanecer Y para que vuelvan a probarse correctamente, incluso si eso tiene que esperar hasta más tarde. (pronto, este ruido hará enojar a alguien lo suficiente como para que hagan algo al respecto, con la esperanza de que algo sea para comenzar a corregirlos).

Ahora, si esa funcionalidad está temporalmente bloqueada, puede desactivar las pruebas hasta que vuelva a visitarla.

Si la funcionalidad se está eliminando (y no se espera que regrese) solo entonces, eliminaré las pruebas.

    
respondido por el RualStorge 02.05.2014 - 22:39
6

No se va a arreglar, ¿por qué?

¿Es algo que se planea arreglar más tarde? Mantener las pruebas.

¿Ya no es relevante toda la funcionalidad (las pruebas están comprobando algo que ya no es cierto)? Vea si puede arreglar las pruebas para verificar la funcionalidad correcta o simplemente eliminar las pruebas si ya existen nuevas pruebas para esa nueva funcionalidad.

    
respondido por el aragaer 02.05.2014 - 22:38
5

Debería ser obvio que no corriges tu código porque falla una prueba de unidad, sino porque tu código hace las cosas incorrectas: la prueba de unidad es solo un indicador, y las pruebas de unidad no siempre son correctas por definición. Si dice "nuestro código es incorrecto pero no podemos molestarnos en repararlo", deje las pruebas de la unidad y sufra la vergüenza. Si dice "nuestro código es correcto, no puede esperar que lo llamen de esa manera", elimine la prueba de la unidad.

Si escribe una función, define las entradas legales y las salidas correctas para cada entrada, entonces se debe eliminar una prueba de unidad que no proporciona entradas legales y falla. Si su código está limitado por la precisión de la aritmética de punto flotante, entonces una prueba que falla porque espera una mayor precisión debería eliminarse. Eso es lo que parece que está pasando aquí.

Cuando dije "entradas legales", eso, por supuesto, podría ser mal interpretado. Puedo escribir una función que espera una dirección de correo electrónico válida como entrada; esa función puede fallar si pasa algo que no es una dirección de correo electrónico válida. Puedo escribir otra función que espere una cadena C terminada en cero que no sea NULL que podría contener cualquier bytes, pero se supone que contiene una dirección de correo electrónico válida en codificación UTF-8. Una prueba de unidad que lo llama con un puntero nulo o una cadena no terminada es incorrecta y debe eliminarse. Pero una prueba unitaria que pasa una cadena válida con datos de basura debe conducir a una detección correcta de los datos de basura, porque con la definición de la función, cualquier información de basura es una "entrada legal" que debe manejarse correctamente (es probable que se identifique y se devuelva un error una excepción lanzada). Y los casos de prueba que van en casos de esquina absoluta de la especificación y esperan que se manejen correctamente también son correctos.

    
respondido por el gnasher729 03.05.2014 - 01:22
3

El mayor problema con los mensajes molestos de los sistemas de mantenimiento, ya sean pruebas automatizadas, archivos de registro o alguna otra fuente de información es que los receptores de esos mensajes se atenúan al ruido y lo desconectan.

En este momento, puede ver tres pruebas de unidad fallidas y pensar: "No es gran cosa", pero es una pendiente resbaladiza. Es probable que no tenga un corredor de prueba lo suficientemente sofisticado como para "ignorar todas las fallas excepto estas tres" para mostrarle una barra verde, y probablemente solo vea vagamente las pruebas de " n , m pasado, x falló "al ejecutar las pruebas.

El propósito de las pruebas unitarias es prestar atención para que no tenga que hacerlo. Esto le permite la libertad de refactorizar con el conocimiento de que las pruebas le indicarán si ha pasado por alto algo.

Parece que piensas que la prueba de la unidad debería mantenerse. En ese caso, debe corregir el código para que la prueba pase, incluso si tiene que inyectar un simulacro para algún otro componente. (Es una prueba unitaria, no una prueba de integración).

    
respondido por el Art Taylor 03.05.2014 - 06:47
1

Yo diría: ¡no! Si dicha prueba de unidad no es necesaria y muestra solo errores pequeños, no debe eliminarla, ya que dicha prueba de unidades es esencial para la planificación futura y para el seguimiento de errores de su aplicación.

En la versión actual, es posible que el error no influya en su aplicación, pero ¿puede garantizar que, para futuras versiones, los requisitos cambien?

saludos Nico

    
respondido por el WhiteIntel 02.05.2014 - 22:32
1

La respuesta obvia es que si los comportamientos no se van a arreglar, de hecho, su comportamiento real no es "inesperado", sino "esperado": se entiende que está en una de cierta manera, y se entiende por qué es así, y se entiende que continuará de esa manera (no será "arreglado").

Tal comportamiento debe codificarse como el comportamiento esperado que valida la prueba de la unidad.

Si pasar NaN a una función produce un falso positivo, escriba la prueba de regresión para que valide esto. Entonces, un día, si pasar NaN a esa función produce un resultado negativo, algo cambió (posiblemente de forma rota).

    
respondido por el Kaz 04.05.2014 - 09:27
1

Hay un continuo en el que caen situaciones como esta. Si necesita la funcionalidad de la prueba de unidad de prueba, obviamente debe mantenerlos. Si nunca lo utilizará nunca, nunca más, y lo sabe y está absolutamente, absolutamente seguro al 100%, debería deshacerse de esas pruebas unitarias. Para cualquier otro nivel de certeza, la respuesta no es tan simple.

Si va a utilizar la funcionalidad, pero no ahora, es posible que desee mantener las pruebas de la unidad, a menos que interfieran con otras pruebas de la unidad o la validación del código. Un paquete de pruebas que he estado usando, BusterJS for Node, tiene un método para poner las pruebas unitarias en "espera" al poner 2 barras al frente del nombre, dentro de su cadena. En efecto, estás "comentando la prueba de salida", aunque Buster todavía sabe que está ahí y te lo muestra. Su conjunto de pruebas puede tener algo como esto: si lo hace, ¡UTILICELO!

Si existe la mínima posibilidad de que alguna vez use la funcionalidad, decida qué tan importante es que se haga la prueba donde la va a usar, qué tan intrusivas son las pruebas y cuánta hinchazón causan, luego decida desde allí. También tenga en cuenta que todo este código tiene un costo en términos de legibilidad y espacio, aunque generalmente hay formas de separarlo definitivamente del resto del código y probablemente no ocupará suficiente espacio adicional para preocuparse. El rendimiento generalmente no es un problema, ya que la aplicación es lo suficientemente inteligente como para no ejecutar las pruebas mientras ejecuta el código de producción.

Finalmente, recuerde que puede tener lo mejor de ambos mundos: las pruebas unitarias existen y se mantienen actualizadas, pero son opcionales en su conjunto de pruebas o no se realizan realmente. La forma de hacerlo depende de usted, pero la mayoría de los lenguajes de programación tienen un concepto llamado "comentar". Probablemente sea así como está escribiendo su documentación, así que, ¿por qué no usarla para cosas que necesita o quiere pero que no está usando ahora? Entonces, si alguna vez necesita usar la prueba, simplemente deje de hacer un comentario. Recuerde mantener las pruebas tan actualizadas como sea necesario o lo desee, probándolas periódicamente.

    
respondido por el trysis 04.05.2014 - 06:10
0

En general debes evitar el código muerto de todo tipo. Independientemente de su producción o código de prueba. Incluso si encuentra argumentos convincentes para mantener un código en particular, lo principal que ven otros desarrolladores es que el código muerto es aceptable y lo harán también. Y debido a que pueden no estar conscientes de sus justificaciones, lo harán por razones mucho menos profundas. Y es cierto que se sumará al ruido general. Ver teoría de la ventana rota.

Si desea mantener este código de prueba ininterrumpido, solo para que le recuerden las suposiciones que hacen sus métodos probados sobre los parámetros de entrada, ¡entonces documente estas suposiciones para el método mismo! O para hacerlo más explícito, puede escribir aserciones explícitas en su método, que pueden servir como documentación y como herramienta de depuración cuando se habilita durante la depuración. Incluso hay marcos de condiciones previas disponibles si desea ir por esa ruta, pero eso no es realmente necesario.

A menudo, el código muerto se puede eliminar sin reemplazo. En otras ocasiones, aún se puede eliminar, pero se debe reemplazar con alguna documentación o algún código real (como las aserciones). Si tiene para mantener el código muerto, asegúrese de documentar los motivos al hacerlo justo encima del bloque de código ofensivo.

    
respondido por el David Ongaro 03.05.2014 - 22:35

Lea otras preguntas en las etiquetas