Calidad de código en pruebas unitarias?

23

Al escribir pruebas unitarias, ¿vale la pena pasar el tiempo extra para que el código tenga buena calidad y legibilidad?

Cuando escribo pruebas, a menudo rompo la Ley de Deméter , para escribir más rápido y evitar el uso de tantas variables. Técnicamente, las pruebas unitarias no se reutilizan directamente; están estrictamente vinculadas al código, por lo que no veo ninguna razón para dedicar mucho tiempo a ellas; solo necesitan ser funcionales.

m3th0dman
fuente
55
La legibilidad y la mantenibilidad deben ser el foco principal de las pruebas unitarias.
EL Yusubov
2
¡Las pruebas también son código!
Grant Palin
Todavía es parte de su proyecto, incluso si no se envía a los clientes. Trátelo en consecuencia.

Respuestas:

11

Definitivamente, debe tomar el mismo cuidado, si no mejor, de sus pruebas unitarias que su código de producción en términos de calidad y legibilidad. Las pruebas unitarias son a menudo lo primero que se observa cuando se trata de comprender lo que hace algún fragmento de código, y el lector debe comprender rápidamente lo que está en juego al mirar la prueba. Las pruebas unitarias también tienden a cambiar mucho y se romperán mucho si su diseño no es robusto, lo que anula los beneficios de tener pruebas.

La violación de la Ley de Deméter es definitivamente un problema en las pruebas de su unidad por ese motivo, así como por otros 2 que se me ocurren:

  • Si sus pruebas infringen la Ley de Demeter en sus secciones Organizar o Actuar , probablemente sea una señal de que su código de producción también lo hace, ya que sus pruebas unitarias son solo otro consumidor de su código y probablemente llamarán y operarán la clase bajo prueba en la misma como lo haría cualquier otro código de producción.

  • Si sus pruebas infringen la Ley de Demeter en sus secciones de Afirmación (es decir, usted verifica el valor de algo que está profundamente anidado en el gráfico de dependencias del objeto bajo prueba), podría ser que realmente sean pruebas de integración en lugar de pruebas unitarias. En otras palabras, si en TestA usted afirma que ABCD es igual a algo, podría ser que realmente está tratando de probar D y A en lugar de solo A.

Por cierto, cuando dices

Rompo muy a menudo la Ley de Deméter, para escribir más rápido y no usar tantas variables.

debes tener en cuenta que escribir

var grab = myDependency.Grab;
var something = grab.Something;
var very = something.Very;

very.Deep();

en realidad no es mejor Demeter sabio que

myDependency.Grab.Something.Very.Deep();

si eso es lo que quisiste decir.

guillaume31
fuente
47

Vale la pena pasar tiempo escribiendo código de buena calidad para pruebas unitarias:

  • Requerirán mantenimiento como cualquier otro código.
  • Las pruebas unitarias son una de las mejores fuentes de documentación para su sistema, y ​​posiblemente la forma más confiable. Realmente deberían mostrar:
    • Intención: "¿Cuál es el comportamiento esperado?".
    • Uso: "¿cómo se supone que debo usar esta API?".
  • Requerirán la depuración como cualquier otro código.

El único factor a favor de un enfoque un poco más ad-hoc es que sus pruebas unitarias nunca serán una API pública, por lo que no debe preocuparse por qué interfaces / etc. estás exponiendo

vaughandroid
fuente
22

Si importa. Hay varias razones por las cuales las pruebas unitarias deben mantenerse en un estándar comparable a otro código:

  • Cada prueba unitaria también sirve como documentación para el examinado. Cuando las pruebas son exhaustivas y cubren tantos casos extremos y condiciones de error como sea posible, a menudo pueden reemplazar la documentación de comentarios de una clase o función. También pueden servir como punto de partida para personas nuevas en la base de código.

  • Las pruebas unitarias también pueden tener errores. Y los errores son más visibles cuando el código está bien escrito.

  • Si, por alguna razón, luego necesita dividir un módulo, es probable que también necesite dividir sus pruebas unitarias. Esto es más fácil si las pruebas se escriben de manera que tengan dependencias fácilmente discernibles.

Dicho esto, siempre está la cuestión de la practicidad. Dependiendo del idioma y la naturaleza de su código, puede ser difícil escribir pruebas unitarias "limpias" sin pasar mucho más tiempo en las pruebas que en el código que deben probar. En ese caso, generalmente recurro a probar las cosas fáciles y rápidas y la funcionalidad más crítica, sin preocuparme demasiado por la cobertura completa. Cada vez que aparece un error en un momento posterior, escribo una prueba para ello y verifico si puedo refactorizar la nueva prueba y las existentes para hacerlas más agradables.

Benjamin Kloster
fuente
12

si no puede leer una prueba unitaria y descubrir qué está probando la próxima vez que falle, pasará el doble del tiempo de depuración (una vez para averiguar de qué se trata la prueba y otra para corregir el código que está probando)

honestamente, las pruebas unitarias deben tener un resultado esperado; hacer procedimiento; obtener un resultado real; prueba esperada contra el tipo real de estructura que es fácil de escribir y entender

monstruo de trinquete
fuente
1

El código de prueba debe recibir tanto amor como su código de producción. Para facilitar la lectura, tal vez incluso más. Si se supone que alguien más que usted (incluido usted dos semanas después de dejar el código) entiende lo que está sucediendo, entonces debe hacer que su código sea agradable y nítido.

Esto significa:

  • Extraiga la creación de datos de prueba en clases de generador.
  • Extraer aserciones multibles en métodos de aserción separados.
  • Sea muy preciso al nombrar. Assert.That(x4, Is.EqualTo(y16*2*SOME_VALUE), ASS_ERR_TXT_56)tiene muy poco sentido para la mayoría de los lectores.

Llevado al extremo, las pruebas se pueden escribir para que sean casi tan fáciles de leer y entender como la prosa. El probador extremo probablemente diría que una prueba unitaria de más de 10 líneas es mala.

Morten
fuente
1

La razón práctica más importante es que cada vez que cambia el código, cambia las pruebas unitarias. Y si está haciendo TDD, incluso está cambiando primero las pruebas unitarias.

Realice cualquiera de estas cosas en sus pruebas:

  • Código duplicado
  • Disminuir la legibilidad
  • Acoplamiento apretado
  • Acoplamiento temporal
  • Alta complejidad ciclomática (muchas dependencias)

Y te espera mucho trabajo cuando se necesita un cambio.

Trate sus pruebas como sugirió, y terminará arrepintiéndose. Probablemente incluso llegue a la falsa conclusión de que "TDD no funciona".

Ñame Marcovic
fuente
0

Depende de si estas pruebas unitarias son "temporales" o no. Si

  1. La prueba se usará con frecuencia;

  2. Los desarrolladores tienen que trabajar con pruebas unitarias escritas por otros desarrolladores;

  3. La mayoría de las pruebas se realizan mediante pruebas unitarias.

entonces las pruebas deben escribirse correctamente. En caso de que haya un error en la prueba en sí, será difícil encontrar el error y solucionarlo, especialmente si ha pasado algún tiempo desde que se escribió la prueba.

Por otro lado, si estas pruebas son utilizadas solo por los propios desarrolladores, entonces creo que está bien. Pero aún así es más preferible escribir código 'legible'. Como dijo Ratchet Freak, pasarás más tiempo arreglando tus pruebas de lo que gastarías en escribirlas correctamente.

superM
fuente
(1) las pruebas unitarias nunca son temporales (2) incluso si son para usted mismo, en un mes (o más), no recordará todos los detalles, por lo tanto, es importante hacerlo correctamente, incluso para usted mismo
BЈовиЈ