unit testing - ejemplo - TDD vs. Pruebas unitarias
tdd pdf (17)
Probablemente logre que el equipo escriba pruebas unitarias una vez que se escribe el código (tal vez como un requisito para verificar el código) y mi suposición es que todavía hay valor al escribir esas pruebas unitarias.
No hay absolutamente ninguna duda sobre el hecho de que hay un valor en el código de unidad probada (independientemente de cuándo se escribieron las pruebas) e incluyo "el código se prueba en unidades" en la "Definición de Hecho". Las personas pueden usar TDD o no, siempre y cuando prueben.
En cuanto al control de versiones, me gusta usar " ramas de desarrollo " con una política probada por unidad (es decir, el código compila y construye, todas las pruebas de unidad pasan). Cuando se realizan las funciones, se publican desde las ramas de desarrollo hasta el tronco. En otras palabras, la rama troncal es la " Sucursal realizada " (¡No hay basura en el maletero!) Y tiene una política de envío (puede lanzarse en cualquier momento) que es más estricta e incluye más cosas que "unidad probada".
Mi empresa es bastante nueva en la prueba unitaria de nuestro código. He estado leyendo sobre TDD y pruebas unitarias durante algún tiempo y estoy convencido de su valor. Intenté convencer a nuestro equipo de que TDD vale la pena el esfuerzo de aprender y cambiar nuestra forma de pensar sobre cómo programamos, pero es una lucha. Lo cual me lleva a mi (s) pregunta (s).
Hay muchos en la comunidad de TDD que son muy religiosos sobre escribir el examen y luego el código (y yo estoy con ellos), pero para un equipo que está luchando con TDD, ¿un compromiso todavía trae beneficios adicionales?
Probablemente logre que el equipo escriba pruebas unitarias una vez que se escribe el código (tal vez como un requisito para verificar el código) y mi suposición es que todavía hay valor al escribir esas pruebas unitarias.
¿Cuál es la mejor manera de traer un equipo en apuros a TDD? Y en su defecto, ¿vale la pena escribir pruebas unitarias, incluso si es posterior a la escritura del código?
EDITAR
Lo que me he alejado de esto es que es importante para nosotros comenzar las pruebas unitarias, en algún lugar del proceso de codificación. Para aquellos en el equipo que recogen el concepto, comiencen a moverse más hacia TDD y probar primero. Gracias por la contribución de todos.
SEGUIR
Recientemente comenzamos un nuevo proyecto pequeño y una pequeña parte del equipo usó TDD, el resto escribió pruebas unitarias después del código. Después de completar la parte de codificación del proyecto, las pruebas de la unidad de escritura después del código se sorprendieron al ver los codificadores TDD ya hechos y con un código más sólido. Era una buena forma de conquistar a los escépticos. Todavía tenemos muchos dolores de crecimiento por delante, pero la batalla de voluntades parece haber terminado. ¡Gracias a todos los que ofrecieron consejos!
¡TDD se trata de diseño! Entonces, si lo usa, tendrá un diseño comprobable de su código, lo que le facilitará la tarea de escribir sus pruebas. Si escribe pruebas después de escribir el código, siguen siendo valiosas, pero en mi humilde opinión perderá tiempo, ya que probablemente no tenga un diseño comprobable.
Una sugerencia que puedo darte para intentar convencer a tu equipo para que adopte TDD es utilizar algunas de las técnicas descritas en el libro de Mary Linn y Linda Rising: Patrones para la introducción de nuevas ideas
Acabo de leer esto en un calendario: "Cada regla, ejecutada al máximo, se vuelve ridícula o incluso peligrosa". Entonces mi sugerencia es no ser religioso al respecto. Cada miembro de su equipo debe encontrar un equilibrio entre lo que sienten "correcto" cuando se trata de las pruebas. De esta forma, cada miembro de tu equipo será más productivo (en lugar de, digamos, pensar "¿por qué tengo que escribir esta prueba sti ****?").
Entonces, algunas pruebas son mejores que ninguna, las pruebas después del código son mejores que algunas pruebas y pruebas antes de que el código sea mejor que después. Pero cada paso tiene sus propios méritos y no debes fruncir el ceño ni siquiera en pequeños pasos.
Bueno, si no escribes pruebas primero, no es "Prueba conducida", solo está probando. Tiene beneficios en sí mismo y si ya tiene una base de código para agregar pruebas, es útil, incluso si no es TDD, sino simplemente una prueba.
Escribir pruebas primero es enfocarse en lo que el código debería hacer antes de escribirlo. Sí, también se hace una prueba y es bueno, pero algunos pueden argumentar que ni siquiera es el punto más importante.
Lo que haría es entrenar al equipo en proyectos de juguete como estos (ver Coding Dojo, Katas) usando TDD (si puedes conseguir que los programadores de TDD con experiencia participen en dicho taller sería incluso mejor). Cuando vean los beneficios, usarán TDD para el proyecto real. Pero mientras tanto no los fuerce, si no ven el beneficio, no lo harán bien.
Comenzar a construir clases de prueba JUnit es la manera de comenzar, para el código existente es la única manera de comenzar. En mi experiencia, es muy útil crear clases de prueba para el código existente. Si la administración piensa que esto invertirá demasiado tiempo, puede proponer solo escribir clases de prueba cuando se encuentre que la clase correspondiente contiene un error o necesita limpieza.
Para el proceso de mantenimiento, el enfoque para hacer que el equipo funcione es escribir pruebas JUnit para reproducir errores antes de arreglarlos, es decir,
- error es reportado
- crear una clase de prueba JUnit si es necesario
- agregue una prueba que reproduzca el error
- arregla tu código
- ejecuta la prueba para mostrar que el código actual no reproduce el error
Puede explicar que al "documentar" los errores de esta manera evitará que esos errores vuelvan a aparecer más tarde. Ese es un beneficio que el equipo puede experimentar de inmediato.
Definitivamente vale la pena escribir las pruebas unitarias después de escribir el código. Es solo que a veces es más difícil porque tu código no fue diseñado para ser comprobado, y es posible que lo hayas complicado demasiado.
Creo que una buena forma pragmática de incorporar un equipo a TDD es proporcionar el método alternativo de "prueba durante el desarrollo" en el período de transición, o posiblemente a largo plazo. Deben ser alentados a secciones de código TDD que les parezcan naturales. Sin embargo, en secciones de código que parecen difíciles de acercarse primero a la prueba o al usar objetos que están predeterminados por un proceso A & D no ágil, los desarrolladores pueden tener la opción de escribir una pequeña sección del código y luego escribir pruebas para cubrir ese código, y repitiendo este proceso. Escribir pruebas de unidad para algún código inmediatamente después de escribir ese código es mejor que no escribir ninguna prueba de unidad en absoluto.
Esto es algo con lo que tu equipo tendrá que tener sus propios éxitos antes de que comiencen a creerlo. Voy a despotricar acerca de mi nUnit Epifanía para cualquiera que se preocupe:
Hace unos 5 años descubrí nUnit cuando trabajaba en un proyecto. Casi habíamos completado V1.0 y creé algunas pruebas solo para probar esta nueva herramienta. Tuvimos muchos errores (¡obviamente!) Porque éramos un equipo nuevo, en un plazo ajustado, altas expectativas (¿te suena familiar?). De todos modos, obtuvimos 1.0 y comenzamos con 1.1. Reorganizamos el equipo un poco y obtuve 2 desarrolladores asignados a mí. Hice una demostración de 1 hora para ellos y les dije que todo lo que escribíamos tenía que tener un caso de prueba. Constantemente corríamos "detrás" del resto del equipo durante el ciclo de desarrollo 1.1 porque estábamos escribiendo más código, las pruebas unitarias. Terminamos trabajando más, pero aquí está la recompensa: cuando finalmente llegamos a las pruebas, teníamos exactamente 0 errores en nuestro código. Ayudamos a todos los demás a depurar y reparar sus errores. En la autopsia, cuando apareció el número de errores, llamó la atención de TODOS.
No soy lo suficientemente tonto como para pensar que puedes poner a prueba tu camino hacia el éxito, pero soy un verdadero creyente en lo que respecta a las pruebas unitarias. El proyecto adoptó nUnit y pronto se extendió a la empresa para todos los proyectos .Net como resultado de 1 éxito. El período de tiempo total para nuestra versión V1.1 fue de 9 semanas de desarrollo, por lo que definitivamente NO fue un éxito de la noche a la mañana. Pero a largo plazo, resultó ser un éxito para nuestro proyecto y la compañía para la que creamos soluciones.
He hecho esto en muchas organizaciones y he encontrado que la mejor forma de iniciar TDD y seguirlo es establecer una programación de pares. Si tienes a alguien más, puedes contar con que conoce TDD, entonces los dos pueden dividirse y vincularse con otros desarrolladores para realmente hacer una programación emparejada usando TDD. Si no, capacitaría a alguien que te ayudará a hacer esto antes de presentarlo al resto del equipo.
Uno de los mayores obstáculos con las pruebas unitarias y especialmente TDD es que los desarrolladores no saben cómo hacerlo, por lo que no pueden ver cómo puede valer la pena su tiempo. También cuando comienzas por primera vez, es mucho más lento y no parece proporcionar beneficios. En realidad, solo te proporciona beneficios cuando eres bueno en eso. Al configurar las sesiones de programación combinadas, puede lograr que los desarrolladores aprendan rápidamente y se vuelvan más rápidos. Además, podrán ver beneficios inmediatos a medida que trabajen juntos.
Este enfoque me ha funcionado muchas veces en el pasado.
No hay duda de que las pruebas (Primero, Mientras o incluso Después) salvarán su tocino y mejorarán su productividad y confianza. ¡Recomiendo adoptarlo!
Estaba en una situación similar, porque era un desarrollador "novato", a menudo me sentía frustrado cuando trabajaba en un proyecto de equipo por el hecho de que una contribución había roto la construcción. No sabía si tenía la culpa o, incluso, en algunos casos, a quién culpar. Pero estaba más preocupado de que estuviese haciendo lo mismo con mis compañeros desarrolladores. Esta realización luego motivó la adopción de algunas estrategias TDD. Nuestro equipo comenzó a tener juegos tontos y reglas, como que no puedes ir a casa hasta que todas tus pruebas pasen, o si presentas algo sin una prueba, entonces tienes que comprar a todos "cerveza / almuerzo / etc." y eso hizo que TDD fuera más divertido.
Puede encontrar algo de tracción al mostrar un ejemplo o dos donde TDD da como resultado que se escriba menos código, ya que solo escribe el código requerido para hacer la prueba, la tentación de dorar o participar en YAGNI es más fácil de resistir. El código que no escribe no necesita mantenimiento, refactorización, etc., por lo que se trata de un "ahorro real" que puede ayudar a vender el concepto de TDD.
Si puede demostrar claramente el valor en términos de tiempo, costo, código y errores guardados, puede encontrar que es una venta más fácil.
Si el equipo está forcejeando en la implementación de TDD, pero no estaban creando pruebas unitarias antes ... entonces comience con la creación de pruebas unitarias después de escribir su código. ¡Incluso las pruebas Unitarias escritas después del código son mejores que ninguna Prueba Unitaria!
Una vez que sean competentes en Unit Testing (y todo lo que viene con eso), entonces puede trabajar para que primero creen las pruebas ... y codifiquen en segundo lugar.
Si son nuevos para las pruebas que el código de prueba de inicio de IMO que ya se ha escrito y gradúense lentamente para escribir pruebas primero. Como alguien que está tratando de aprender TDD y pruebas de unidades nuevas, he encontrado que es difícil hacer un 180 completo y cambiar mi mentalidad para escribir pruebas antes del código, por lo que el enfoque que estoy tomando es una especie de mezcla 50-50 ; cuando sé exactamente cómo se verá el código, escribiré el código y luego escribiré una prueba para verificarlo. Para situaciones en las que no estoy del todo seguro, comenzaré con una prueba y trabajaré hacia atrás.
También recuerde que no hay nada de malo en escribir pruebas para verificar el código, en lugar de escribir código para satisfacer las pruebas. Si su equipo no quiere tomar la ruta TDD, no la fuerce.
Si tiene sesiones de diseño antes de escribir el código o tiene que producir un documento de diseño, entonces podría agregar Pruebas unitarias como el resultado tangible de una sesión.
Esto podría servir como una especificación de cómo debería funcionar su código. Aliente el emparejamiento en la sesión de diseño, para hacer que la gente hable sobre cómo debería funcionar algo y qué debería hacer en escenarios determinados. ¿Cuáles son los casos límite, con casos de prueba explícitos para que todos sepan lo que va a hacer si se les da un argumento nulo por ejemplo?
Un lado, pero BDD también puede ser de interés
TDD es una herramienta que los desarrolladores pueden usar para producir un mejor código. Siento que el ejercicio de escribir un código comprobable es tan valioso como las pruebas mismas. El aislamiento de la IUT (implementación bajo prueba) para propósitos de prueba tiene el efecto secundario de desacoplar su código.
TDD no es para todos, y no hay magia que haga que un equipo decida hacerlo. El riesgo es que los escritores de pruebas unitarias que no saben lo que vale la pena probar escribirán muchas pruebas de bajo valor, que serán carne de cañón para los escépticos de TDD en su organización.
Por lo general, las Pruebas de aceptación automatizadas no son negociables, pero les permite a los desarrolladores adoptar TDD a su gusto. Mis experimentados TDD capacitan / asesoran al resto y "prueban" la utilidad mediante el ejemplo durante un período de muchos meses.
Esto es tanto un cambio social / cultural como técnico.
Una manera poderosa de descubrir los beneficios de TDD es hacer una reescritura significativa de algunas funcionalidades existentes, tal vez por razones de rendimiento. Al crear un conjunto de pruebas que hacen un buen trabajo cubriendo toda la funcionalidad del código existente, esto le da la confianza para refactorizarse hasta el contenido de su corazón con plena confianza de que sus cambios son seguros.
Tenga en cuenta que en este caso estoy hablando de probar el diseño o el contrato: las pruebas unitarias que prueban los detalles de implementación no serán adecuadas aquí. Pero, una vez más, TDD no puede probar la implementación por definición, ya que se supone que deben escribirse antes de la implementación.
Uno de los aspectos más útiles de las pruebas unitarias es garantizar la corrección continua del código que ya funciona. Cuando pueda refactorizar a voluntad, deje que un IDE le recuerde los errores de tiempo de compilación y luego haga clic en un botón para que sus pruebas detecten cualquier posible error de tiempo de ejecución, llegando a veces a bloques de código previamente triviales, entonces creo que encontrará su equipo comenzando a apreciar TDD. Entonces, comenzar con las pruebas del código existente es definitivamente útil.
Además, para ser franco, he aprendido más sobre cómo escribir código comprobable al intentar probar el código escrito que a partir de TDD. Al principio, puede ser demasiado abstracto si intenta pensar en contratos que logren el objetivo final y permitan las pruebas. Pero cuando mira el código y puede decir "Este singleton aquí arruina por completo la inyección de dependencia y hace que probar esto sea imposible", comienza a apreciar los patrones que facilitan la vida de prueba.
En mi humilde opinión, es mejor tener una cobertura de prueba del 50% con "código primero, prueba después" y una biblioteca completa al 100%, que la cobertura del 100% de prueba y una biblioteca completa al 50% con TDD. Después de un tiempo, tus compañeros desarrolladores esperan que les resulte entretenido y educativo escribir pruebas para todo el código public
que escriben, por lo que TDD se infiltrará en su rutina de desarrollo.