Encuentro las pruebas mucho más difíciles y difíciles de escribir que el código real que están probando. No es inusual que pase más tiempo escribiendo la prueba que el código que está probando.
¿Es normal o estoy haciendo algo mal?
Las preguntas “ ¿Merecen la pena las pruebas unitarias o el desarrollo basado en pruebas? "," Pasamos más tiempo implementando pruebas funcionales que implementando el sistema en sí, ¿es esto normal? ”Y sus respuestas son más sobre si las pruebas valen la pena (como en" ¿deberíamos omitir las pruebas de escritura por completo? "). Si bien estoy convencido de que las pruebas son importantes, me pregunto si pasar más tiempo en las pruebas que el código real es normal o si solo soy yo.
A juzgar por la cantidad de puntos de vista, respuestas y votos positivos que recibió mi pregunta, solo puedo asumir que es una preocupación legítima que no se aborda en ninguna otra pregunta en el sitio web.
fuente
Respuestas:
Recuerdo de un curso de ingeniería de software, que uno gasta ~ 10% del tiempo de desarrollo escribiendo código nuevo, y el otro 90% es depuración, prueba y documentación.
Dado que las pruebas unitarias capturan la depuración y el esfuerzo de prueba en el código (potencialmente automatizable), tendría sentido que se dedique más esfuerzo a ellos; el tiempo real empleado no debería ser mucho más que la depuración y las pruebas que se realizarían sin escribir las pruebas.
Finalmente, las pruebas también deberían funcionar como documentación. Uno debe escribir pruebas unitarias en la forma en que se pretende usar el código; es decir, las pruebas (y el uso) deben ser simples, poner las cosas complicadas en la implementación.
Si sus pruebas son difíciles de escribir, ¡el código que prueban probablemente sea difícil de usar!
fuente
Está.
Incluso si solo realiza pruebas unitarias, no es inusual tener más código dentro de las pruebas que el código realmente probado. No tiene nada de malo.
Considere un código simple:
¿Cuáles serían las pruebas? Hay al menos cuatro casos simples para probar aquí:
El nombre de la persona es
null
. ¿Se produce realmente una excepción? Eso es al menos tres líneas de código de prueba para escribir.El nombre de la persona es
"Jeff"
. ¿Recibimos"Hello, Jeff!"
respuesta? Eso son cuatro líneas de código de prueba.El nombre de la persona es una cadena vacía. ¿Qué salida esperamos? ¿Cuál es el resultado real? Pregunta secundaria: ¿coincide con los requisitos funcionales? Eso significa otras cuatro líneas de código para la prueba unitaria.
El nombre de la persona es lo suficientemente corto para una cadena, pero demasiado largo para combinarlo con
"Hello, "
el signo de exclamación. ¿Qué pasa?Esto requiere una gran cantidad de código de prueba. Además, las piezas de código más elementales a menudo requieren un código de configuración que inicializa los objetos necesarios para el código que se está probando, lo que a menudo también lleva a escribir trozos y simulaciones, etc.
Si la relación es muy grande, en cuyo caso puede verificar algunas cosas:
¿Hay duplicación de código en las pruebas? El hecho de que sea un código de prueba no significa que el código deba duplicarse (copiado-pegado) entre pruebas similares: dicha duplicación dificultará el mantenimiento de esas pruebas.
¿Hay pruebas redundantes? Como regla general, si elimina una prueba unitaria, la cobertura de la rama debería disminuir. Si no es así, puede indicar que la prueba no es necesaria, ya que las rutas ya están cubiertas por otras pruebas.
¿Está probando solo el código que debe probar? No se espera que pruebe el marco subyacente de las bibliotecas de terceros, sino exclusivamente el código del proyecto en sí.
Con las pruebas de humo, las pruebas de sistema e integración, las pruebas funcionales y de aceptación y las pruebas de estrés y carga, agrega aún más código de prueba, por lo que tener cuatro o cinco LOC de pruebas para cada LOC del código real no es algo de lo que deba preocuparse.
Una nota sobre TDD
Si le preocupa el tiempo que lleva probar su código, es posible que lo esté haciendo mal, es decir, primero el código, luego las pruebas. En este caso, TDD puede ayudarlo al alentarlo a trabajar en iteraciones de 15 a 45 segundos, cambiando entre código y pruebas. De acuerdo con los defensores de TDD, acelera el proceso de desarrollo al reducir tanto la cantidad de pruebas que debe hacer como, y lo que es más importante, la cantidad de código comercial para escribir y especialmente reescribir para pruebas.
¹ Let n sea la longitud máxima de una cadena . Podemos llamar
SayHello
y pasar por referencia una cadena de longitud n - 1 que debería funcionar bien. Ahora, en elConsole.WriteLine
paso, el formato debe terminar con una cadena de longitud n + 8, lo que dará como resultado una excepción. Posiblemente, debido a los límites de memoria, incluso una cadena que contiene n / 2 caracteres dará lugar a una excepción. La pregunta que uno debe hacerse es si esta cuarta prueba es una prueba unitaria (parece una, pero puede tener un impacto mucho mayor en términos de recursos en comparación con las pruebas unitarias promedio) y si prueba el código real o el marco subyacente.fuente
personName
ajustes en astring
, pero el valor depersonName
más los valores concatenados se desbordanstring
.As a rule of thumb, if you remove a unit test, the branch coverage should decrease.
Si escribo las cuatro pruebas que mencionó anteriormente y luego elimino la tercera prueba, ¿disminuirá la cobertura?Creo que es importante distinguir entre dos tipos de estrategias de prueba: pruebas unitarias y pruebas de integración / aceptación.
Aunque la prueba de la unidad es necesaria en algunos casos, con frecuencia se realiza sin remedio. Esto se ve exacerbado por las métricas sin sentido forzadas en los desarrolladores, como "100% de cobertura". http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf proporciona un argumento convincente para esto. Considere los siguientes problemas con las pruebas unitarias agresivas:
Las pruebas de integración / aceptación, por otro lado, son una parte muy importante de la calidad del software y, en mi experiencia, debería dedicar una cantidad significativa de tiempo a hacerlas bien.
Muchas tiendas han bebido el TDD kool-aid, pero como lo muestra el enlace anterior, varios estudios muestran que su beneficio no es concluyente.
fuente
.equals()
métodos generados por Eclipse". Escribí un instrumento de prueba paraequals()
ycompareTo()
github.com/GlenKPeterson/TestUtils~~V~~singular~~1st Casi todas las implementaciones que he probado era deficiente. ¿Cómo se usan las colecciones siequals()
yhashCode()
no funcionan juntas de manera correcta y eficiente? Estoy animando nuevamente por el resto de su respuesta y la he votado. Incluso reconozco que algunos métodos equals () generados automáticamente pueden no necesitar pruebas, pero he tenido tantos errores con implementaciones deficientes que me pone nervioso.No se puede generalizar.
Si necesito implementar una fórmula o un algoritmo a partir del renderizado basado en la física, es muy posible que pase 10 horas en pruebas unitarias paranoides, ya que sé que el más mínimo error o falta de precisión puede dar lugar a errores que son casi imposibles de diagnosticar, meses después. .
Si solo quiero agrupar lógicamente algunas líneas de código y darle un nombre, solo usado en el alcance del archivo, es posible que no lo pruebe en absoluto (si insiste en escribir pruebas para cada función, sin excepción, los programadores podrían retroceder) para escribir la menor cantidad de funciones posible).
fuente
Sí, es normal si estás hablando de TDDing. Cuando tiene pruebas automatizadas, asegura el comportamiento deseado de su código. Cuando escribe sus pruebas primero, determina si el código existente ya tiene el comportamiento que desea.
Esto significa que:
(Esto no tiene en cuenta la refactorización de código, que tiene como objetivo pasar menos tiempo escribiendo código posterior. Se equilibra con la refactorización de prueba, que tiene como objetivo pasar menos tiempo escribiendo pruebas posteriores).
Sí, también, si estás hablando de escribir exámenes después del hecho, pasarás más tiempo:
De lo que gastarás en realidad escribiendo código.
Entonces sí, es una medida esperada.
fuente
Creo que es la parte más importante.
La prueba de unidad no siempre se trata de "ver si funciona bien", sino de aprender. Una vez que prueba algo lo suficiente, se "codifica" en su cerebro y finalmente reduce el tiempo de prueba de su unidad y puede encontrarse escribiendo clases y métodos completos sin probar nada hasta que termine.
Es por eso que una de las otras respuestas en esta página menciona que en un "curso" hicieron un 90% de pruebas, porque todos necesitaban aprender las advertencias de su objetivo.
La prueba de unidad no solo es un uso muy valioso de su tiempo, sino que literalmente mejora sus habilidades, es una buena manera de revisar su propio código nuevamente y encontrar un error lógico en el camino.
fuente
Puede ser para muchas personas, pero depende.
Si está escribiendo pruebas primero (TDD), es posible que experimente cierta superposición en el tiempo dedicado a escribir la prueba que es realmente útil para escribir el código. Considerar:
Al escribir pruebas después de escribir el código, puede descubrir que su código no es fácilmente comprobable, por lo que escribir pruebas es más difícil / lleva más tiempo.
La mayoría de los programadores han estado escribiendo código mucho más tiempo que las pruebas, por lo que espero que la mayoría de ellos no sean tan fluidos. Además, puede agregar el tiempo necesario para comprender y utilizar su marco de prueba.
Creo que tenemos que cambiar nuestra mentalidad sobre cuánto tiempo lleva codificar y cómo están involucradas las pruebas unitarias. Nunca lo mire a corto plazo y nunca compare el tiempo total para ofrecer una función particular porque debe considerar no solo escribir un código mejor / menos defectuoso, sino un código que sea más fácil de cambiar y aún así hacerlo mejor / menos con errores.
En algún momento, todos somos capaces de escribir código que es tan bueno, por lo que algunas de las herramientas y técnicas solo pueden ofrecer mucho para mejorar nuestras habilidades. No es como si pudiera construir una casa si solo tuviera una sierra guiada por láser.
fuente
Sí lo es. Con algunas advertencias.
En primer lugar, es "normal" en el sentido de que la mayoría de las grandes tiendas funcionan de esta manera, por lo que incluso si esta forma fue completamente equivocada y tonta, el hecho de que la mayoría de las grandes tiendas trabajen de esta manera lo hace "normal".
Con esto no quiero decir que probarlo sea incorrecto. He trabajado en entornos sin pruebas y en entornos con pruebas obsesivo-compulsivas, y aún puedo decirles que incluso las pruebas obsesivo-compulsivas fueron mejores que ninguna prueba.
Y todavía no hago TDD (quién sabe, podría hacerlo en el futuro), pero hago la gran mayoría de mis ciclos de edición-ejecución-depuración ejecutando las pruebas, no la aplicación real, así que, naturalmente, trabajo mucho en mis pruebas, para evitar todo lo posible tener que ejecutar la aplicación real.
Sin embargo, tenga en cuenta que existen peligros en las pruebas excesivas, y específicamente en la cantidad de tiempo que se dedica a mantener las pruebas. (Estoy escribiendo principalmente esta respuesta para señalar específicamente esto).
En el prefacio de The Art of Unit Testing (Manning, 2009) de Roy Osherove , el autor admite haber participado en un proyecto que fracasó en gran parte debido a la tremenda carga de desarrollo impuesta por las pruebas unitarias mal diseñadas que tuvieron que mantenerse durante todo el proceso. duración del esfuerzo de desarrollo. Entonces, si te encuentras pasando demasiado tiempo haciendo nada más que mantener tus pruebas, esto no significa necesariamente que estás en el camino correcto, porque es "normal". Su esfuerzo de desarrollo podría haber entrado en un modo poco saludable, donde podría ser necesario un replanteamiento radical de su metodología de prueba para guardar el proyecto.
fuente
fuente