Pregunta

Marcos simulados, por ejemplo, EasyMock, hace que sea más fácil conectar dependencias ficticias. Dicho esto, usarlos para garantizar cómo se llaman los diferentes métodos en componentes particulares (y en qué orden) me parece malo. Expone el comportamiento a la clase de prueba, lo que dificulta el mantenimiento del código de producción. Y realmente no veo el beneficio; mentalmente siento que he estado encadenado a una bola pesada.

Me gusta mucho más probar contra la interfaz, dar datos de prueba como entrada y afirmar el resultado. Mejor aún, usar alguna herramienta de prueba que genere datos de prueba automáticamente para verificar una propiedad determinada. p.ej. al agregar un elemento a una lista, y al eliminarlo de inmediato se obtiene la misma lista.

En nuestro lugar de trabajo, usamos Hudson, que proporciona cobertura de prueba. Desafortunadamente, hace que sea fácil obsesionarse ciegamente con que todo está probado. Creo firmemente que uno no debería probar todo si quiere ser productivo también en modo de mantenimiento. Un buen ejemplo serían los controladores en frameworks web. Como generalmente deben contener muy poca lógica, las pruebas con un marco simulado que el controlador llama a tal o cual método en un orden particular no tienen sentido en mi opinión sincera.

Estimados SOers, ¿qué opinan sobre esto?

¿Fue útil?

Solución

Depende de cómo modeles los dominios de tu programa.

Si modela los dominios en términos de datos almacenados en estructuras de datos y métodos que leen datos de una estructura de datos y almacenan datos derivados en otra estructura de datos (procedimientos o funciones según el procedimiento o la funcionalidad de su diseño), entonces simula los objetos No son apropiados. Lo que se llama " basado en estado " prueba es lo que quieres. El resultado que le interesa es que un procedimiento coloca los datos correctos en las variables correctas y lo que requiere para que eso suceda es solo un detalle de la implementación.

Si modela los dominios en términos de protocolos de comunicación de paso de mensajes por medio de los cuales colaboran los objetos, entonces los protocolos son lo que le interesa y los datos que los objetos almacenan para coordinar su comportamiento en los protocolos en los que desempeñan roles es solo una implementación detalle. En ese caso, los objetos simulados son la herramienta correcta para el trabajo y las pruebas basadas en el estado vinculan las pruebas demasiado a los detalles de implementación sin importancia.

Y en la mayoría de los programas orientados a objetos hay una mezcla de estilos. Algún código será escrito puramente funcional, transformando estructuras de datos inmutables. Otro código coordinará el comportamiento de los objetos que cambian su estado interno oculto a lo largo del tiempo.

En cuanto a la alta cobertura de pruebas, realmente no te dice mucho. La cobertura de prueba baja le muestra dónde tiene pruebas inadecuadas, pero la cobertura de prueba alta no le muestra que el código se haya probado adecuadamente. Las pruebas pueden, por ejemplo, ejecutar rutas de código y, por lo tanto, aumentar las estadísticas de cobertura, pero en realidad no hacer ninguna afirmación sobre lo que hicieron esas rutas de código. Además, lo que realmente importa es cómo se comportan las diferentes partes del programa en combinación, qué cobertura de prueba de unidad no le dirá. Si desea verificar que sus pruebas realmente están probando el comportamiento de su sistema adecuadamente, podría usar una herramienta de Pruebas de mutación. Es un proceso lento, por lo que es algo que se ejecutaría en una compilación nocturna en lugar de en cada registro.

Otros consejos

Leí 2 preguntas:

¿Cuál es su opinión sobre la prueba de que los métodos particulares de los componentes se llaman en un orden particular?

Me he enojado con esto en el pasado. Usamos mucho más " stubbing " y mucho menos " burla " estos días. Intentamos escribir pruebas unitarias que solo prueban una cosa. Cuando hacemos esto, normalmente es posible escribir una prueba muy simple que apaga interacciones con la mayoría de los otros componentes. Y muy raramente afirmamos ordenar. Esto ayuda a que las pruebas sean menos frágiles.

Las pruebas que solo prueban una cosa son más fáciles de entender y mantener.

Además, si tiene que escribir muchas expectativas para las interacciones con muchos componentes, de todos modos podría haber un problema en el código que está probando. Si es difícil mantener las pruebas, el código que está probando a menudo se puede refactorizar.

¿Debe uno estar obsesionado con la cobertura de prueba?

Cuando escribo pruebas de unidad para una clase dada estoy bastante obsesionado con la cobertura de la prueba. Hace que sea muy fácil detectar partes importantes de comportamiento que no he probado. También puedo hacer un juicio sobre qué partes no necesito cubrir.

¿Estadísticas generales de cobertura de pruebas unitarias? No está particularmente interesado siempre que sean altos.

¿100% de cobertura de prueba unitaria para un sistema completo? No estoy interesado en absoluto.

Estoy de acuerdo: estoy a favor de inclinarme fuertemente hacia la verificación del estado en lugar de la verificación del comportamiento (una interpretación vaga de TDD clásica mientras se sigue utilizando la prueba de dobles).

El libro El arte de las pruebas unitarias tiene muchos buenos consejos en estas áreas.

100% de cobertura de prueba, prueba de GUI, prueba de obtención / configuración u otro código no lógico, etc. parece poco probable que proporcione un buen retorno de la inversión. TDD proporcionará una alta cobertura de prueba en cualquier caso. Prueba lo que podría romperse.

Hice una pregunta similar ¿Cuánto prueba de unidad es un Good Thing , que podría ayudar a dar una idea de la variedad de niveles de prueba que las personas consideran apropiados.

  1. ¿Cuál es la probabilidad de que, durante el mantenimiento de su código, algún empleado subalterno rompa la parte del código que ejecuta " llama al controlador tal y tal método en un orden particular " ;?

  2. ¿Cuál es el costo para su organización si esto ocurre? En la interrupción de la producción, la depuración / reparación / re-prueba / relanzamiento, el riesgo legal / financiero, el riesgo de reputación, etc. ...

Ahora, multiplique # 1 y # 2 y verifique si su reticencia a lograr una cantidad razonable de cobertura de prueba vale la pena el riesgo.

A veces, no lo será (es por eso que en las pruebas hay un concepto de un punto de rendimientos decrecientes).

Por ejemplo, Si mantiene una aplicación web que no es crítica para la producción y tiene 100 usuarios que tienen una solución alternativa si la aplicación está dañada (y / o puede hacer una reversión fácil e inmediata), entonces pasar 3 meses haciendo la cobertura de prueba completa de esa aplicación probablemente no sea -sensible.

Si trabaja en una aplicación en la que un error menor puede tener consecuencias multimillonarias o peores (piense en el software del transbordador espacial o el sistema de guía para un misil de crucero), entonces las pruebas exhaustivas con cobertura completa se vuelven mucho más sensuales. .

Además, no estoy seguro de si estoy leyendo demasiado sobre su pregunta, pero parece estar insinuando que tener una prueba de unidad habilitada de manera burlona de alguna manera excluye las pruebas funcionales de integración / aplicación. Si ese es el caso, tiene razón en objetar esa noción: los dos enfoques de prueba deben coexistir.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top