¿Se utilizan realmente las pruebas unitarias como documentación?

22

No puedo contar el número de veces que leo declaraciones en la línea de "las pruebas unitarias son una fuente muy importante de documentación del código bajo prueba". No niego que sean ciertas.

Pero personalmente no me he encontrado usándolos como documentación, nunca. Para los marcos típicos que uso, las declaraciones de métodos documentan su comportamiento y eso es todo lo que necesito. Y supongo que la unidad prueba la copia de seguridad de todo lo que se indica en esa documentación, más probablemente algunas cosas más internas, por lo que, por un lado, duplica la ducumentación, mientras que por el otro puede agregar algo más que es irrelevante.

Entonces la pregunta es: ¿cuándo se usan las pruebas unitarias como documentación? Cuando los comentarios no cubren todo? ¿Por desarrolladores que extienden la fuente? ¿Y qué exponen que puede ser útil y relevante que la documentación en sí no puede exponer?

stijn
fuente
44
Nunca pensé en usar la prueba unitaria directamente como documentación. Creo que las pruebas unitarias a menudo son ilegibles, porque muchos desarrolladores no se toman el tiempo para escribirlas con claridad.
SuperM
10
Los comentarios pueden estar equivocados.
2
Sé que está preguntando específicamente sobre las pruebas unitarias, pero también me gustaría señalar que las pruebas de integración / sistema también son una documentación realmente útil, solo que a un nivel diferente
jk.
3
He visto pruebas unitarias que se caracterizarían mejor como "experimentos unitarios". Su dependencia de factores externos era tanto que los hacía casi inútiles. También fueron muy poco claros. (Sí, tengo un objetivo a largo plazo para refactorizarlos para que sean mejores, pero también hago otras cosas ...)
Donal Fellows
44
Las pruebas de la unidad @Ant invocan el código real y documentan la respuesta esperada y la comparan con la respuesta real. Si el código invocado es correcto o no, no es el punto: las pruebas documentan cómo invocarlo.

Respuestas:

17

NO son una documentación de referencia ABSOLUTA

Tenga en cuenta que gran parte de lo siguiente también se aplica a los comentarios, ya que pueden desincronizarse con el código, como las pruebas (aunque es menos exigible).

Entonces, al final, la mejor manera de entender el código es tener un código de trabajo legible .

Si es posible y no se escriben secciones de código de bajo nivel cableadas o condiciones particularmente complicadas, la documentación adicional será crucial.

  • Las pruebas pueden estar incompletas:
    • La API cambió y no se probó,
    • La persona que escribió el código escribió las pruebas para los métodos más fáciles de probar primero en lugar de los métodos más importantes para probar, y luego no tuvo tiempo de terminar.
  • Las pruebas pueden ser obsoletas.
  • Las pruebas pueden cortocircuitarse de manera no obvia y no ejecutarse realmente.

PERO TODAVÍA son un complemento de documentación ÚTIL

Sin embargo, cuando tengo dudas sobre lo que hace una clase en particular, especialmente si es bastante larga, oscura y falta de comentarios (ya sabes el tipo ...), trato de encontrar rápidamente su (s) clase (s) de prueba y compruebo:

  • lo que realmente intentan verificar (da una pista sobre los datos más importantes, excepto si el desarrollador cometió el error mencionado anteriormente de solo implementar las pruebas "fáciles"),
  • y si hay casos de esquina.

Además, si se escriben usando un estilo BDD , dan una definición bastante buena del contrato de la clase . Abra su IDE (o use grep) para ver solo nombres de métodos y tada: tiene una lista de comportamientos.

Las regresiones y los errores también necesitan pruebas

Además, es una buena práctica escribir pruebas de regresión y de informes de errores: arreglas algo, escribes una prueba para reproducir el caso. Al mirar hacia atrás, es una buena manera de encontrar el informe de error relevante y todos los detalles sobre un problema anterior, por ejemplo.

Yo diría que son un buen complemento para la documentación real, y al menos un recurso valioso a este respecto. Es una buena herramienta, si se usa correctamente. Si comienzas a probar temprano en tu proyecto y lo conviertes en un hábito, PODRÍA ser una muy buena documentación de referencia. En un proyecto existente con malos hábitos de codificación que ya huelen la base del código, trátelos con cuidado.

haylem
fuente
¿Puedo preguntar por qué me votaron negativamente? ¿Qué te molesta allí o con qué no estás de acuerdo?
haylem
2
La mejor parte (IMO) de su argumento está escrita en la fuente más pequeña: la mejor manera de entender el código es tener un código legible en primer lugar. Cambiaría eso a "código legible y funcional", pero estoy de acuerdo. Luego, si observa nuevamente las pruebas unitarias, las pruebas en ejecución son un código que funciona (y, como todo código, debería ser legible), por lo que en realidad es una documentación bastante buena (si a menudo demasiado local) cuando se hace bien.
Joris Timmermans
@MadKeithV: gracias. Actualicé para "código legible y de trabajo" y subí un poco más.
haylem
11

Una interpretación es que las pruebas unitarias son "documentación ejecutable". Puede ejecutar las pruebas unitarias contra el código y le dirá si todavía está funcionando como cuando las pruebas se escribieron para aprobar, o no. De esa manera, la unidad prueba el "documento" de la funcionalidad del sistema en algún momento, de forma ejecutable.

Por otro lado, también rara vez he leído el código de prueba de la unidad como "documentación" para comprender la funcionalidad. Una prueba de una sola unidad es demasiado localizada, específica y abstracta para poder decirle mucho sobre el sistema real que está detrás de la clase que se está probando.

Joris Timmermans
fuente
5

Si por documentación quiere decir que quiero algo para descubrir cómo funciona el código , las pruebas unitarias son pequeños ejemplos perfectos de cómo funcionan las unidades del código en los casos esperados , de borde y de error (también conocidos como errores ). Además, sus pruebas podrían crearse antes de que se escriba el código, lo que subyace a lo que debe hacer el código desde el punto de vista comercial / de requisitos.

¿Están reemplazando la documentación? No.

¿Son una adición útil a la documentación? Sí.

Sardathrion - Restablece a Monica
fuente
4

Veo pruebas unitarias como:

  • una forma de demostrar que la documentación es correcta (suponiendo que la documentación coincida con la implementación de la API).
  • una forma de mostrarle a un desarrollador cómo usar una característica particular; los dispositivos de prueba de unidad / prueba de unidad en sí son generalmente lo suficientemente pequeños como para que uno pueda aprender rápidamente de ella.
  • y obviamente para detectar cualquier error de regresión.

Hasta cierto punto, pueden verse como un complemento de una documentación existente, pero no como la documentación.

David Andreoletti
fuente
3

Voy a responder tu pregunta preguntándote otra.

¿Con qué frecuencia al trabajar con una nueva API / rutina ha ayudado a buscar un ejemplo de código de lo que está tratando de usar? ¿No puede cambiar a google para buscar en línea muestras de código?

Eso es exactamente cuando usaría pruebas unitarias como documentación.

  • De hecho, las pruebas unitarias pueden ser un poco más rigurosas que los ejemplos de código normales, ya que debe tener múltiples pruebas (ejemplos).
  • Esperemos que sus pruebas unitarias ilustren el uso adecuado . Por ejemplo, muestran claramente todas las dependencias esenciales, ya sea a través de objetos normales u objetos simulados. (De lo contrario, no son pruebas unitarias particularmente buenas).
  • NOTA: Si sus comentarios o "documentación normal" proporcionan ejemplos de código, en realidad está violando los principios DRY. Y esos ejemplos de código pueden fácilmente volverse incorrectos con el tiempo, mientras que hay significativamente menos posibilidades de eso con las pruebas unitarias ejecutadas regularmente.
  • Si las pruebas unitarias son exhaustivas (generalmente un gran if ), entonces deben proporcionar información adicional:
    • Todos los casos límite conocidos claramente ilustrados.
    • Todas las excepciones esperadas que se pueden lanzar.
    • Todos los errores encontrados anteriormente (esto probablemente sea más útil al extender la unidad bajo prueba que al escribir un nuevo cliente para la unidad).
    • Todas las reglas comerciales subyacentes asociadas con la unidad. (Si alguna)

Sospecho que hay bastantes razones por las que las pruebas unitarias no tienden a usarse como documentación, aunque podrían ser un excelente complemento para la documentación más tradicional:

  • Me atrevería a sugerir que a menudo las pruebas en sí mismas no están suficientemente escritas para tal fin. Otras respuestas ya han aludido a pruebas que son:
    • Incompleto.
    • Confuso. (He visto casos de prueba que no llaman al método bajo prueba directamente: vas 3/4 niveles de profundidad en la pila de llamadas antes de que se llame y las condiciones previas para llamar al método se encuentran dispersas en diferentes lugares en una compleja jerarquía de clases. )
    • Anticuado. (por lo general, las pruebas deben fallar cuando quedan desactualizadas, pero este no es siempre el caso).
  • Por lo general, hay muchos ejemplos de uso disponibles en el código de producción cada vez que surge la necesidad de un ejemplo.
  • La unidad bajo prueba está tan bien escrita (autodocumentada) que los métodos no necesitan ejemplos. ¡Yo deseo!
  • En mi experiencia como programador, tendemos a tener muchas ganas de saltar al extremo profundo y RTFM el próximo martes ...
  • Documentación y comentarios que violen el principio DRY.
Desilusionado
fuente
2

TL; las pruebas de unidad DR y los comentarios de API son complementarios: algunas cosas se describen mejor en código y otras en prosa.

Las pruebas unitarias son principalmente útiles para documentar casos especiales y condiciones de borde que son difíciles (y engorrosos) de describir en los comentarios de la API. Además, los comentarios de la API generalmente se dirigen a las personas que desean utilizar la API.

Si desea modificar el código, generalmente hay mucho más que necesita saber, y algo de eso es difícil de poner en los comentarios (y estos comentarios quedan obsoletos rápidamente). En ese caso, una prueba unitaria también funciona como documentación.

Un ejemplo: tiene un método m (a, b)que realiza un cierto cálculo. Debido a los requisitos de compatibilidad con versiones anteriores, debe incluir entradas de casos especiales de a=0y a=-1, pero solo si bes NULL. Poner eso en un comentario es complicado, detallado y es probable que quede obsoleto si el requisito se elimina más adelante.

Si realiza algunas pruebas unitarias que verifican el comportamiento de m(0, NULL), m(-1, x)obtiene varios beneficios:

  • La descripción del comportamiento correcto es clara, se reducen los malentendidos
  • Las personas no pueden pasar por alto el requisito cuando cambian el código, a diferencia de un comentario
sleske
fuente
pero para su ejemplo, si ese comportamiento no está documentado en el comentario, un usuario puede obtener resultados inesperados para ese caso límite. Lo cual no es exactamente una buena cosa.
stijn
@stijn: Cierto. En ese caso, la mejor manera probablemente sería tener una breve mención del caso especial en los documentos, además de las pruebas unitarias para los detalles desordenados.
sleske