¿Merecen la pena las pruebas unitarias o el desarrollo basado en pruebas?

48

Mi equipo en el trabajo se está mudando a Scrum y otros equipos están comenzando a hacer un desarrollo basado en pruebas usando pruebas unitarias y pruebas de aceptación del usuario. Me gustan los UAT, pero no estoy convencido de realizar pruebas unitarias para desarrollo basado en pruebas o desarrollo basado en pruebas en general.

Parece que escribir pruebas es un trabajo extra, da a las personas una muleta cuando escriben el código real y puede no ser efectivo con mucha frecuencia.

Entiendo cómo funcionan las pruebas unitarias y cómo escribirlas, pero ¿alguien puede argumentar que es realmente una buena idea y que vale la pena el esfuerzo y el tiempo?

Además, ¿hay algo que haga que TDD sea especialmente bueno para Scrum?

Owen Johnson
fuente
27
Si desea asegurarse de que su software se dañe con frecuencia, sea más o menos completamente imposible de mantener y deba reemplazarse antes de que esté realmente listo para la producción; entonces le sugiero que prescinda completamente de las pruebas unitarias y nunca se tome el tiempo de aprender TDD.
Dawood dice que reinstalar a Monica el
3
Piense en el deseo / necesidad de un refactorizador. ¿Te sentirías más seguro de hacer la refactorización (de cualquier magnitud) con o sin un conjunto completo de pruebas unitarias para atraparte cuando accidentalmente has roto algo?
Marjan Venema
2
¿"Le da a la gente una muleta cuando escriben código real"? ¿No pueden describirse la mayoría de las mejores prácticas de esta manera?
user16764
44
@DavidWallace: Este es el problema de los desarrolladores incompetentes, no la falta de TDD. Además, incluso cuando TDD se usa ampliamente, da cero garantías de que el cambio que realizó no rompa nada.
Codificador
66
@NimChimpsky: No tengo ninguna negatividad hacia TDD, simplemente no estoy siguiendo el bombo publicitario. Tiene sus lados positivos y negativos también. La falsa sensación de seguridad es uno de ellos.
Codificador

Respuestas:

68

Respuesta corta: absolutamente positiva.

Respuesta larga: Las pruebas unitarias son una de las prácticas más importantes que intento influir en mi lugar de trabajo (banco grande, operaciones de cambio). Sí, son trabajo extra, pero es un trabajo que paga una y otra vez. Las pruebas unitarias automatizadas no solo lo ayudan a ejecutar el código que está escribiendo y, por supuesto, a verificar sus expectativas, sino que también actúan como una especie de perro guardián para futuros cambios que usted u otra persona puedan hacer. Se producirá una rotura de la prueba cuando alguien cambie el código de manera indeseable. Creo que el valor relativo de las pruebas unitarias disminuye en correlación con el nivel de cambio y crecimiento esperado en una base de código, pero la verificación inicial de lo que hace el código hace que valga la pena incluso cuando el cambio esperado es bajo. El valor de la prueba unitaria también depende del costo de los defectos. Si el costo (donde el costo es la pérdida de tiempo / dinero / reputación / esfuerzo futuro) de un defecto es cero, entonces el valor relativo de una prueba también es cero; Sin embargo, este casi nunca es el caso en un entorno comercial.

Por lo general, ya no contratamos personas que habitualmente no crean pruebas unitarias como parte de su trabajo; es algo que esperamos, como aparecer todos los días. No he visto un análisis de costo beneficio puro de tener pruebas unitarias (alguien se siente libre de señalarme una), sin embargo, puedo decir por experiencia que en un entorno comercial, vale la pena probar que el código funciona en un sistema importante grande. . También me permite dormir mejor por la noche sabiendo que el código que he escrito funciona de manera comprobable (hasta cierto nivel), y si cambia, alguien será alertado de cualquier efecto secundario inesperado por una construcción rota.

El desarrollo impulsado por pruebas, en mi opinión, no es un enfoque de prueba. En realidad, es un enfoque / práctica de diseño con el resultado de ser el sistema de trabajo y un conjunto de pruebas unitarias. Soy menos religioso acerca de esta práctica, ya que es una habilidad que es bastante difícil de desarrollar y perfeccionar. Personalmente, si estoy construyendo un sistema y no tengo una idea clara de cómo funcionará, emplearé TDD para ayudarme a encontrar mi camino en la oscuridad. Sin embargo, si estoy aplicando un patrón / solución existente, normalmente no lo haré.

En ausencia de pruebas matemáticas para usted de que tiene sentido escribir pruebas unitarias, le animo a que lo pruebe durante un período prolongado y experimente los beneficios usted mismo.

rupjones
fuente
55
Lo que me gustaría agregar es que las pruebas unitarias también te hacen pensar en el diseño de tu interfaz. Cuando llegas a una parte en la que piensas "¿cómo pruebo la unidad métodos privados?", Sabes que probablemente sea tu interfaz la que está mal.
TC1
1
"Le animo a que lo pruebe durante un período prolongado y experimente los beneficios usted mismo". Solo intentarlo una vez fue suficiente para mí, los beneficios parecían obvios.
NimChimpsky
1
+1 para "Por lo general, ya no contratamos personas que habitualmente no crean pruebas unitarias como parte de su trabajo". Recientemente tuve que rechazar a un candidato que, entre otras deficiencias, proclamó firmemente que no le gusta escribir pruebas automáticas porque son una pérdida de tiempo y podría probar el código él mismo.
ftr
44
no puede probar que un código no trivial funciona de manera relevante simplemente usando pruebas automatizadas. Con las pruebas automatizadas, solo puede probar que el código pasa las pruebas : si las pruebas cubren el 100% de sus casos de uso, probablemente tenga su "cierto nivel", pero eso no significa que el código "funcione". Para tener una probabilidad real, necesitaría en.wikipedia.org/wiki/Formal_verification ; como tal, está usando el término "probablemente" incorrecto aquí.
vaxquis
1
@vaxquis sí, tienes toda la razón sobre el uso del término prueba. Pero apostaría a que la presencia de pruebas (o la práctica de TDD) es una mejor evidencia de un sistema de trabajo que la ausencia de pruebas.
rupjones
16

Los errores encontrados antes son menos costosos de reparar que los errores encontrados más tarde. TDD lo ayuda a verificar la corrección de su sistema. Invierte un poco más por adelantado, pero lo recupera más tarde. El gráfico es un poco exagerado, pero muestra bien la idea.

ingrese la descripción de la imagen aquí

Fuente de imagen

Martin Wickman
fuente
¿Qué quieres decir con tradicional ? ¿Algo que no sea TDD?
Giorgio
No parece que este gráfico se base en algunas estadísticas reales, solo representa la experiencia de una sola persona que escribió esta entrada de blog en 2006. No es que esté diciendo que esté completamente equivocado, pero la realidad es mucho más complicada.
Doc Brown
9

¿Merecen la pena las pruebas unitarias o el desarrollo basado en pruebas?

Sí lo hace . Tío Bob (Robert C Martin) dijo en una presentación;

Para que un desarrollador demuestre que su código funciona mejor para escribir una prueba y aprobarla que gritar, cantar o bailar al respecto.

Y dado que no va a eliminar la prueba, siempre que la prueba sea aprobada, está seguro de que la funcionalidad está funcionando : los problemas de regresión están resueltos.

Hay muchas cosas escritas en él,

  1. Usted es responsable de hacer que esa característica funcione. Escribe una prueba. Simplemente hazlo.
  2. Cuándo reemplazar las pruebas unitarias con la prueba de integración

¿Están relacionados SCRUM, pruebas unitarias y TDD?

En breve, cuando seas un maestro, Unit testingestarás cerca TDD. SCRUM no tiene nada que ver con esto, pero como dicen, las grandes cosas se mezclan bien, estas técnicas de desarrollo de software se suman en una excelente pila , si aún no lo has probado, pruébalo.

¿Hay algo que haga que TDD sea especialmente bueno para SCRUM?

Como dije anteriormente , hacen una buena combinación ; Si le agrega algunas pruebas de automatización, entonces es más especial .

ManuPK
fuente
8

Parece que escribir pruebas es un trabajo extra, da a las personas una muleta cuando escriben el código real y puede no ser efectivo con mucha frecuencia.

Las pruebas unitarias tienen valor como muleta. Es compatible con sus esfuerzos de desarrollo, lo que le permite cambiar su implementación sin temor a que su aplicación deje de funcionar según sea necesario. Las pruebas unitarias también son mucho más que una muleta, ya que le brindan una herramienta con la que puede validar que su implementación cumpla con los requisitos.

Todas las pruebas, ya sean pruebas unitarias, pruebas de aceptación, pruebas de integración, etc., son tan efectivas como las personas que las usan. Si aborda su trabajo de manera descuidada, sus pruebas serán descuidadas y su implementación tendrá problemas. ¿Entonces, para qué molestarse? Se molesta en probar porque necesita probarse a usted mismo y a sus clientes que su software funciona y no tiene ningún problema que pueda evitar que se use el software. Sí, las pruebas son definitivamente un trabajo extra, pero la forma en que realice las pruebas determinará cuánto esfuerzo necesitará para corregir los errores después del lanzamiento, y cuánto esfuerzo requerirá su código para cambiar y mantener.

Entiendo cómo funcionan las pruebas unitarias y cómo escribirlas, pero ¿alguien puede argumentar que es realmente una buena idea y que vale la pena el esfuerzo y el tiempo?

TDD, y realmente cualquier método que requiera que usted escriba pruebas antes de codificar toma el enfoque que puso en un esfuerzo temprano como un anticipo de la deuda técnica futura. A medida que trabaja en el proyecto, cualquier cosa que se pierda o que no se implemente bien incurrirá en una deuda más técnica en forma de una mayor dificultad de mantenimiento, que afecta directamente los costos futuros y los requisitos de recursos. Las pruebas por adelantado aseguran que no solo ha hecho un esfuerzo para abordar la deuda técnica futura, sino que también asegura que codifica sus requisitos de tal manera que puedan verificarse simplemente ejecutando su código. La prueba primero también le brinda la oportunidad de validar su comprensión del dominio del problema antes de comprometerse a resolver el problema en el código, y valida sus esfuerzos de implementación.

Realmente se trata de intentar maximizar el valor comercial de su código. El código que en gran medida no se ha probado y es difícil de mantener es generalmente barato y rápido de crear, y muy costoso de mantener durante la vida útil del producto después del lanzamiento. El código que se ha probado exhaustivamente a nivel de la unidad es generalmente más costoso de crear, pero su mantenimiento es relativamente bajo durante la vida útil del producto después del lanzamiento.

Además, ¿hay algo que haga que TDD sea especialmente bueno para SCRUM?

TDD no es específicamente bueno para ninguna metodología en particular. Es simplemente una herramienta. Una práctica que puede integrar en sus procesos de desarrollo para ayudarlo a lograr sus resultados específicos. Entonces, para responder a su pregunta, TDD es complementario a su método, ya sea SCRUM o cualquier otro enfoque.

S.Robins
fuente
6

La gente piensa que es un esfuerzo adicional porque es una actividad inicial. Lo que pierdes a tiempo ahora lo recuperas más tarde.

Mis razones para las pruebas unitarias también incluyen:

Te da un objetivo: no puedes escribir una prueba si no sabes qué debe hacer el software. Esto ayuda a eliminar problemas en las especificaciones más temprano que tarde.

Te da una sensación de progreso.

Le advierte si un cambio de código altera la salida de otras áreas de código. Eso facilita la refactorización.

Proporciona una capa adicional de documentación (especialmente si comenta sus pruebas correctamente).

Fomenta todo tipo de buenas prácticas. Debido a que las pruebas deben ejecutarse rápidamente, lo alienta a escribir código que está desacoplado y admite burlas. Todo esto ayuda a refactorizar.

También hay otros cubiertos en otras publicaciones en este hilo. Vale la pena.

Ian
fuente
2

¿Merecen la pena las pruebas unitarias o el desarrollo basado en pruebas?

Definitivamente sí (ver las otras respuestas)

[¿Es] realmente una buena idea y vale la pena el esfuerzo y el tiempo?

  • Sí, si comienza algo nuevo (agregue un nuevo módulo o una aplicación completamente nueva)
  • No, si ya hay un montón de código existente que no se desarrolló con prueba y que debe extenderse (heredado).

En mi opinión, el desarrollo basado en pruebas es más efectivo si escribe las pruebas unitarias antes del código real. De esta manera, el código que cumple las pruebas se separa claramente con un mínimo de referencias externas que es fácilmente comprobable.

Si el código ya existe sin las pruebas unitarias, generalmente es mucho trabajo adicional escribir las pruebas unitarias después porque el código no se escribió para una prueba fácil.

Si hace TDD, el código automáticamente se puede comprobar fácilmente.

k3b
fuente
2

Déjame abordar esto desde el otro lado. ¿Qué sucede cuando desarrolla una aplicación no trivial sin pruebas unitarias? Si tiene un buen departamento de control de calidad, una de las primeras cosas que sucederá es que encontrará que tiene una gran cantidad de problemas reportados. Por qué porque no probaste lo que hiciste y asumiste que funcionaría y porque no prestaste mucha atención a los requisitos y tu aplicación no los cumple. Vuelve al tablero de dibujo para reescribir y arreglar. Ahora ha realizado las correcciones y ha encontrado un conjunto completamente nuevo de problemas porque no tenía forma de verificar que sus correcciones no afectaron nada más antes de pasar al control de calidad. Vaya, la fecha límite ha llegado y se ha ido y la administración está molesta.

La situación es peor si no tienes un buen departamento de control de calidad porque entonces los usuarios encontrarán los errores y eso no solo hará que tu jefe sea infeliz, sino que puede poner de rodillas al entorno de producción y cientos o incluso miles de personas estarán en un punto muerto mientras corrige los errores que las pruebas unitarias habrían evitado. Esta NO es una buena elección de carrera.

Ahora supongamos que este enfoque de vaquero continúa por años. Ahora, cada cambio, incluso los triviales, parece generar nuevos problemas insospechados. No solo eso, sino que muchas de las cosas que le gustaría hacer para que la aplicación funcione mejor, no puede hacerlo porque son demasiado riesgosas o demasiado caras o ambas. Por lo tanto, coloca parches en los parches, lo que hace que el sistema sea cada vez más complicado y más complicado y más difícil de usar.

Los usuarios comienzan a cuestionar sus estimaciones de tiempo porque se vuelven cada vez más grandes y es difícil explicarles que el sistema se ha convertido en un desastre tan complicado, es difícil encontrar dónde hacer los cambios y aún más difícil asegurarse de que no No rompas otra cosa.

Trabajé en un lugar como este donde después de diez años de desarrollo, prácticamente nada de lo que queríamos hacer para solucionar los problemas reales se podía hacer porque no podíamos saber cuál de los cientos de aplicaciones cliente personalizadas se romperían. Los desarrolladores iniciales fueron en gran medida el tipo de desarrolladores de "pruebas unitarias, no necesitamos pruebas de unidades malolientes". Todos los que los siguieron sufrieron gracias a su miopía.

Sin pruebas unitarias, el software es más problemático y lleva más tiempo desarrollarlo y mantenerlo inicialmente. ¿Por qué demonios no querrías hacer pruebas unitarias? El tiempo que dedique a escribir la prueba será mucho menor que el tiempo que dedicaría a solucionar los problemas que debería haber encontrado antes (cuanto antes se encuentre el error, menos tiempo llevará solucionarlo) y los problemas que habría evitado por completo escribiendo las pruebas. primero, lo que proporciona una mejor comprensión de los requisitos antes de comenzar a codificar.

HLGEM
fuente
1

Todo el código que escriba debe probarse en algún momento. No quieres escribir todo de una vez y luego presionar el botón de compilación y cruzar los dedos. Usted escribe y compila pequeños bloques y envía entradas cuidadosamente elaboradas a su código para verificar que hace lo que cree que hace. Luego, generalmente elimina su aparato de prueba ad-hoc y pasa al siguiente componente.

Con las pruebas unitarias, simplifica este proceso y le da una excusa para mantener sus pruebas. De esa manera, si realiza cambios que rompan las cosas que había probado en el pasado, puede detectar esa regresión explícitamente en lugar de permitir que afecte a otras partes de su código. Hay un valor real en eso.

En cuanto al enfoque refactor rojo-verde para TDD, me parece un poco tedioso. Pero a cada cual lo suyo.

tylerl
fuente
1
Para mi 2c: para saber si sus pruebas realmente funcionan, debe verlas fallar antes de verlas pasar. Lamentablemente, he visto a muchos desarrolladores escribir pruebas que parecían estar funcionando, sin embargo, cuando se cambiaron las condiciones de prueba, el código aún pasaría la prueba, aunque debería haber fallado. Si la prueba falla primero y pasa la segunda, es más probable que haya escrito una prueba sin error. Si termina modificando la prueba después de que el código ha cambiado, entonces no puede estar seguro de que el código sea correcto. Sí, es tedioso, pero tiene una mejor oportunidad de ser correcto. :-)
S.Robins
0

La mayoría de las veces encuentro que los desarrolladores son resistentes a la idea de escribir pruebas. No es tanto que argumenten que las pruebas no tienen valor, sino que son simplemente un medio para descubrir cómo resolver un problema en particular. Por lo general, este problema cambia según el contexto. Una vez hecho esto, las pruebas no sirven para nada y bien podrían eliminarse. Aquí hay una muestra de contextos que mis colegas han dado en el pasado sobre cómo decidir cuándo escribir una prueba y encontrará que la única respuesta posible según ellos nunca es:

  • El problema en cuestión debe ser un ejemplo de libro de texto para TDD, como una pila o una calculadora
  • el código trivial no debe probarse (invalida el argumento anterior)
  • el código crítico o difícil debe probarse a fondo (implícito en un argumento anterior)
  • las pruebas no deben estar acopladas a la implementación para permitir una refactorización amplia (invalida el argumento anterior)
  • no es necesario realizar pruebas para detectar efectos secundarios, como llamar a un servicio de terceros con una carga útil específica (por lo tanto, no es necesario realizar pruebas de caja negra)

En realidad, hay un tipo de prueba que he encontrado es generalmente aceptada y que creo que en última instancia es inútil. Es decir, pruebas basadas en GUI, como el uso de selenio, webdriver, watir o arquillian. Así es como obtenemos los ciclos de construcción de 7 horas en lugar de los ciclos de construcción de 5 minutos en mis proyectos TDD.

Estos mismos desarrolladores generalmente se quejan con todos los demás de cuán malo es el código y cuán incompetentes deben haber sido los desarrolladores anteriores. También les resulta extremadamente importante que hagas un diseño adecuado con una pizarra, MS Office o un wiki y ten mucho cuidado para asegurarte de que este diseño se mantenga actualizado.

Ese último es lo que realmente me hizo darme cuenta de que tales desarrolladores son fraudes. Todos sabemos que cualquier documento de diseño que no sea una prueba unitaria quedará desactualizado y no se mantendrá actualizado debido al costo de mantenimiento. De hecho, he intentado e intenté encontrar un buen medio para expresar ideas de diseño en formato MS Office que fuera útil y legible tanto antes como después de escribir código. Fallé en todos los casos y, aunque hay personas que logran producir un documento de MS Office que parece bonito, en realidad nunca los he encontrado útiles.

Entonces, tienes una opción. Puede hacer diseño y documentación practicando TDD, que es el único método conocido y comprobado para producir dicha documentación basado en mis 10 años de experiencia en desarrollo. O puedes entrar en política.

Sebastian Gozin
fuente
1
Las pruebas no son documentación. TDD es una buena práctica, pero muchas veces los desarrolladores usan las herramientas de generación automática que escupen trozos de prueba demasiado simplificados. Si tiene un desarrollador que es resistente a esto, en lugar de escribir pruebas finamente detalladas, intente escribir un arnés de prueba más grande que ejercite más del producto completo. Lo encontrarán obviamente útil. Sin embargo, todavía tiene que escribir la documentación adecuada, no hay forma de escapar de eso.
gbjbaanb
@gbjbaanb: si los desarrolladores usan herramientas de generación automática, tal vez haya pruebas de unidad de escritura, pero definitivamente no TDD. En TDD se supone que debes escribir la prueba antes que los métodos. No puede automatizar el scafolding de la prueba de un método que aún no existe. También las pruebas bien escritas son documentación (documentación técnica para otros desarrolladores del proyecto, no requisitos ni manual de usuario). Las pruebas unitarias bien escritas y mantenidas le muestran cómo los métodos deberían ser pruebas. Y si las pruebas se verifican regularmente y tienen éxito, obviamente son más precisas que la documentación obsoleta. No puedes negar eso.
kriss
unittests puede ser una muy buena documentación para desarrolladores, ya que muestran ejemplos de cómo se puede usar la API.
k3b
El objetivo del selenio, el controlador web, etc. es que no es necesario realizar un control de calidad manual del sitio web. Por lo tanto, no está ahorrando tiempo al eliminarlos de su proceso de compilación, porque ellos mismos están destinados a ahorrar tiempo.
Muhd