plantilla - metodologia tdd
TDD-¿Cómo empezar realmente a pensar en TDD? (19)
He estado leyendo sobre metodologías ágiles, XP y TDD.
He estado en proyectos que dicen que debe hacer TDD, pero la mayoría de las pruebas son de alguna manera pruebas de integración o, durante el transcurso del proyecto, se olvida OTD en un esfuerzo por terminar los códigos más rápido.
Por lo tanto, en lo que respecta a mi caso, he escrito pruebas unitarias, pero empiezo a escribir código primero en lugar de escribir una prueba. Siento que hay un cambio de pensamiento / diseño / paradigma que en realidad es enorme. Entonces, aunque uno realmente cree en TDD, en realidad terminas volviendo al viejo estilo debido a la presión del tiempo / los entregables del proyecto.
Tengo pocas clases en las que tengo un código de unidad pura probado, pero parece que no puedo continuar con el proceso, cuando las burlas entran en escena. Además, a veces veo: el síndrome "¿no es demasiado trivial para escribir una prueba para eso"?
¿Cómo piensan que debería manejar esto?
"Entonces, aunque uno realmente cree en TDD, en realidad terminas volviendo al viejo estilo debido a la presión del tiempo / los resultados del proyecto".
En realidad, no creo que esto sea posiblemente cierto.
Si está "volviendo al viejo estilo", la única razón puede ser porque no cree que TDD produzca mejor código más rápidamente.
Creo que alguien deja de usar TDD porque creen que es mejor producir código pobre más rápidamente.
¿Cómo piensan que debería manejar esto?
Sugiero que piense que su unidad prueba como diálogos con su objeto (suponiendo que esté programando con un lenguaje habilitado para OO como Java, C #, Ruby, PHP, etc.)
Cree una clase de caso de prueba, piense en su método de prueba sobre la interacción que desea tener con sus objetos. Imagina que estás hablando con una máquina inteligente usando el método que pasas a tus objetos como verbos, y luego usa Asserts para verificar que los objetos hayan reaccionado de la manera que quieres que reaccionen.
Después de un tiempo, es posible que disfrutes de este estilo de programación tanto que no esperarías programar sin él ;-)
Por lo tanto, en lo que respecta a mi caso, he escrito pruebas unitarias, pero empiezo a escribir código primero en lugar de escribir una prueba. Siento que hay un cambio de pensamiento / diseño / paradigma que en realidad es enorme. Entonces, aunque uno realmente cree en TDD, en realidad terminas volviendo al viejo estilo debido a la presión del tiempo / los entregables del proyecto.
Es posible que desee tratar de ser absolutamente disciplinado sobre TDD durante un período fijo, por ejemplo, un par de semanas o un mes. Cuando se descubra escribiendo el código antes de las pruebas, bórrelo y comience nuevamente con una prueba fallida. Haga esto hasta que sepa que puede hacerlo, hasta que sepa lo que se siente, y luego tenga la capacidad de hacerlo, y la libertad de tomar una decisión informada, y entienda que está bien si esa opción a veces es codificar primero . Pero no permita que el hábito lo aleje de las buenas prácticas. Primero descifre las buenas prácticas y luego elija cuándo aplicarlas (y, por supuesto, puede encontrar que la respuesta a eso es "siempre", también).
Tengo pocas clases en las que tengo un código de unidad pura probado, pero parece que no puedo continuar con el proceso, cuando las burlas entran en escena. Además, a veces veo: el síndrome "¿no es demasiado trivial para escribir una prueba para eso"?
Las burlas son una cosa: ¿eres bueno con ellas todavía? Si no te sientes cómodo con los simulacros, y estás en una situación en la que los simulacros son apropiados, entonces practica hasta que, como TDD, seas bueno con ellos.
Con respecto al tema "demasiado trivial", no durante las primeras semanas. Solo TDD todo el tiempo. Y cuando descubras que TDD te conduce a un mejor diseño, incluso para el código "demasiado trivial", ten en cuenta. Piensa en cómo se vería tu código sin eso. Y puede descubrir que ningún código es demasiado trivial para TDD. O no. Pero mi punto es, pruébalo, en serio, durante un período significativo, y luego podrás tomar mejores decisiones. Póngase cómodo con eso, luego evalúe.
Tu TDD Mantra por el día ...
La T en TDD es TODO o Tarea impulsada
Prefiero animar a las personas a considerar que TDD se trata de establecer tareas (también conocidas como Pruebas o Especificaciones). (Las tareas incompletas son rojas, las tareas completas son verdes).
Tener un corredor de pruebas continuo que muestre los resultados de sus pruebas / especificaciones es una gran ayuda para adquirir el hábito de las pruebas. Personalmente, creo que es este ciclo de retroalimentación lo que hace que TDD se sienta productivo / alentador de inmediato.
Por supuesto, en el momento en que comienzas a refactorizar y alterar la base de código, obtienes comentarios inmediatos sobre los errores de regresión, y eso es parte del beneficio.
Programa de par haciendo TDD (Idealmente con alguien mejor que usted),
Incluso si es durante tu tiempo libre
TDD es una de esas habilidades donde, al menos para mí, es fácil ser peor de lo que creo que soy. Mi habilidad para TDD siempre mejora cuando estoy en un proyecto de TDD y programo un par con alguien que pueda señalarme cuando podría estar haciendo TDD mejor. Incluso la programación en pareja con alguien que no lo conoce mejor que yo, me ayuda a desarrollar mis ideas mejor que trabajar solo.
Encuentre (o comience) un Retiro de código o un dojo de codificación con un enfoque específico en programación de pares y TDD.
Si su empresa lo permite, organice uno en horario de la empresa o, al menos, in situ en su empresa, incluso si solo es una hora a la semana o durante el almuerzo.
Compre " Test Driven Development: By Example " por Kent Beck, y léalo.
Luego, escribe una prueba de unidad fallida.
Cuando estás en un gran lío de código heredado, encontré que Trabajar eficazmente con Legacy Code es extremadamente útil. Creo que mejorará su motivación para asignar TDD, aunque se trata de escribir pruebas unitarias antes de realizar ningún cambio en su antiguo código heredado. Y desde el fondo de tu pregunta, parece que esta es la posición en la que has estado.
Y, por supuesto, muchos otros señalaron la disciplina . Después de un tiempo forzándote a ti mismo, te olvidarás de por qué lo hiciste de otra manera.
Disciplina.
Tome la decisión de usar TDD y cúmplalo, es una cuestión de su propia capacidad para comprometerse con un proceso y llegar a una conclusión.
El código trivial es donde se esconden los errores. Principalmente pienso que es la naturaleza humana leer lo que se pretendía que estuviera allí en lugar de lo que está allí.
He intentado disciplinarme a mí mismo para seguir TDD en todos mis nuevos proyectos: es difícil romper viejos hábitos, pero creo que vale la pena. Parece tomar más tiempo ya que hay más codificación por adelantado, pero el tiempo de depuración es muy bajo.
No pienses en cómo probarías el código mientras lo escribes. Escriba pruebas que ejerciten cómo debería funcionar el código, luego escriba lo más simple que haga pasar las pruebas. Enjabona, enjuaga, repite. Es probable que tu código no sea como tú imaginabas, pero definitivamente funcionará mejor.
Además, es importante que escribas tus pruebas para que fallen. Escribir pruebas que aprueben no ayudará a encontrar defectos. Y esta es otra muy buena razón para escribir las pruebas primero: si primero escribe el código y luego las pruebas, sus pruebas se escribirán para pasar el código y (sin intención) sesgadas para probar el código en lugar del resultado deseado. ¿Y cómo sabrá que sus pruebas fallarían en ausencia del código correcto? Como las pruebas son solo código, también son susceptibles a los errores.
Así que primero escriba su prueba, luego codifique, poco a poco, en paralelo. Usa las pruebas para afirmar que tu código es correcto y usa el código para afirmar que tus pruebas son correctas (sí, puede suceder que estés seguro de que tu algoritmo es perfecto, pero las pruebas siguen fallando, todo porque cometiste un error estúpido en la prueba. Lo hice esta mañana).
Es muy difícil comenzar con TDD si estás en el vacío, y es casi imposible hacerlo cuando otras personas en tu equipo solo están prestando atención a TDD. Mi consejo es encontrar un lugar (dentro o fuera del trabajo) en el que pueda programar por su cuenta, o mejor aún con un amigo o colega comprometido, y simplemente comenzar a hacerlo, todo el tiempo, y sin excepción.
TDD (y ágil para el caso) solo comienza a hacer clic cuando usted y su equipo están detrás y se comprometen a hacerlo funcionar. Debes obtener algunas victorias TDD en tu haber, y eso hará que creas en ti. LUEGO regresa a tus otros proyectos y sé un campeón para ello. Comience en algún lugar donde pueda obtener esas victorias tempranas cruciales sin embargo. Eso hace toda la diferencia.
Es sencillo:
By learning to think about the "What" __before__ you think about the "How"
En otras palabras, piense exactamente qué quiere hacer (interfaz), en lugar de cómo lo va a hacer (implementación)
TDD, como herramienta de diseño, basada en mi experiencia, realmente te ayuda a ver las cosas desde la perspectiva del usuario en lugar de desde la perspectiva del codificador. Además, creo que TDD ayuda a tu mente a pensar realmente qué estás tratando de hacer exactamente, cuál es el resultado esperado, etc.
Así que la próxima vez, cuando estés probando "TDD", pregúntate qué es lo que intentas hacer y simplemente comienza a escribir el código que expresa tu intención.
Ejemplo:
Diga, alguien quiere que les escriba un sumador entero.
La persona que no tiene un TDD mindest simplemente lo hará:
int add(int a, int b)
{
return a + b;
}
¿Es correcto el código anterior? Claro que lo es. Pero este enfoque, basado en mi experiencia, falla cuando tienes un componente complicado para escribir. (Es por eso que hiciste esta pregunta en primer lugar; lo sé, ya había estado allí antes (¿tal vez aún?)
Lo bueno de TDD es que te obliga a prestar atención ante todo a la interfaz (el qué) del sistema, sin pedirte la implementación de inmediato (el cómo).
En otras palabras, si alguien me pidiera que escribiera un sumador, tendría algo como:
void assertOnePlusTwoEqualThree()
{
assert( add(1,2) == 3 );
}
Observe cómo, incluso antes de siquiera pensar en cómo se supone que debe funcionar el complemento (), ya he resuelto algunas cosas. Es decir, ya lo descubrí:
- la interfaz de mi sumador tanto entradas como salidas
- el primer caso de prueba trivial (prueba de unidad gratis !!)
luego implementa el complemento ().
Mira, no importa si la lógica que se discute aquí es tan simple de implementar. Tener una mentalidad TDD, es aplicarlo todo el tiempo sin excepción. Tienes que hacerlo tantas veces que ni siquiera lo pienses más. Es solo parte de cómo diseñas. Puedo decir esto porque vi que me pasó profesionalmente (tomó cerca de un año de perseverancia).
De la misma manera que si siempre hace un buen trabajo en la programación, independientemente de la complejidad que tenga entre manos, abordará su trabajo de la misma manera.
Por último, creo que TDD es comparable a "bocetos de código". Es decir, comienzas a probar para ver si la interfaz funciona bien para cada escenario (caso de prueba). Entonces está bien si terminas cambiando la interfaz, los nombres, etc. Mira, lo que he aprendido es que muchas veces, el diseño se trata simplemente de comprender el problema a fondo. TDD es una herramienta que te permite hacer eso.
La mente humana, IMO, funciona más fácilmente con ejemplos concretos (casos de prueba / escenarios) en lugar de pensamiento abstracto (cómo implementar algo). Al tener casos de prueba, le permite a su mente aprender gradualmente sobre el problema que está tratando de resolver.
Está bien no saber (volver a la forma "tradicional" ... relájate, deja que tu mente se adapte). Está bien si no es perfecto (escribir un código de implementación está perfectamente bien ... tu cerebro solo está tratando de resolver las cosas). Solo sigue intentándolo, sigue leyendo, sigue codificando, ¡pero nunca te rindas! =)
IMO, TDD con prueba / código / refactor: suena genial y divertido, pero:
- no hay una regla dura que deba hacerse en esa secuencia
- Muchas veces, me encontré escribiendo el código y luego escribiendo las pruebas y encontrando pepitas interesantes que extrañé
- Otras veces, fui a test> code> refactor cycle y lo disfruté de todos modos.
- Creo que el aspecto importante es tener un código probado por la unidad y una cobertura suficiente para garantizar que todos los caminos importantes estén cubiertos. El orden de lograrlo no es tan crítico.
HTH.
EDITAR: Para aclarar mis puntos más
- Aunque prefiero comenzar con las pruebas de escritura, a veces es más fácil entender el paisaje escribiendo código (especialmente para nuevas funcionalidades y / o nuevos proyectos) y luego escribiendo pruebas.
- Pero, si estoy refabricando el código y / o solucionando errores, primero verificaré si las pruebas están escritas y cubren suficientemente lo que está haciendo el código. Si no, primero escribiré la prueba y luego haré la refactorización.
Intenta practicar el código kata .
Un kata está destinado a ser memorizado. Los estudiantes de un kata lo estudian como una forma, no como una conclusión. No es la conclusión del kata lo que importa, son los pasos que conducen a la conclusión. Si quieres inclinarte para pensar de la manera en que pienso, para diseñar la forma en que diseño, entonces debes aprender a reaccionar a las minucias de la manera en que reacciono. Seguir este formulario te ayudará a hacer eso. A medida que aprende la forma, la repite y la repite, condicionará su mente y su cuerpo para responder de la manera en que respondo a los factores minuciosos que conducen a las decisiones de diseño.
Los códigos kata me han dado una idea de cómo se supone que debe sentirse TDD. Sé más pronto cuando estoy empezando a perder el ritmo, a volver a los viejos hábitos. En ese momento, sé que necesito tomar pasos más pequeños, ejecutar las pruebas con más frecuencia, asegurarme de que no estoy tratando de refactorizar en rojo, etc.
Me parece interesante que ninguna de las respuestas hasta ahora haya tocado lo que considero una visión fundamental de las prácticas modernas de desarrollo, y esa es la forma "anticuada" de escribir software reuniendo requisitos, haciendo análisis y modelando lo que se desea sistema antes de escribir cualquier código realmente tenía mucho que ofrecer.
TDD realmente encarna esto hasta cierto punto .
Para escribir una prueba, primero debe saber, para decirlo en términos muy simples, cuáles serán sus aportaciones y cuáles serán sus resultados esperados.
Una vez que tenga ese conocimiento, puede escribir una prueba para ejercitar algún fragmento de código mítico y también, hasta cierto punto, con qué otros artefactos interactuará ese código, antes de escribir ese código o crear esos artefactos.
Esto es lo que anteriormente llamaríamos "ingeniería de requisitos" y "análisis de sistemas" en los viejos métodos de "cascada".
Más allá de eso, descubrirá que una vez que comprenda los requisitos en este nivel, las pruebas de redacción llegarán naturalmente (es, después de todo, simplemente la expresión en el código de la declaración de funcionalidad incorporada en esos requisitos).
Y al escribir el código que expresa los requisitos en forma de pruebas, identificará las lagunas y los malentendidos en los requisitos antes de que haya cometido esas lagunas y malentendidos en el proyecto en forma de código ejecutable.
Para los practicantes modernos de métodos "ágiles" admitir que están involucrados en una serie de "cascadas" es, creo, demasiado vergonzoso, por lo que esta necesidad de requisitos de ingeniería y comprensión se ofusca detrás del lenguaje que habla sobre la necesidad de abordar estas cosas mientras trataba desesperadamente de evitar admitir que "ágil" (como comúnmente se entiende, o tal vez incomprendido) arrojó al bebé con gran parte del agua del baño.
Mi equipo está tratando de mejorar al seguir un enfoque TDD. Tengo que decir que no es lo más fácil con un equipo de desarrollo más grande.
Todos en el equipo necesitan pensar primero con su sombrero de prueba antes de escribir cualquier código de producción. Esto puede ser difícil, ya que a pesar de lo que las personas digan que harán, no hay garantía una vez que lleguen a su teclado.
Para algunos gerentes, puede parecer que el TDD es un enfoque costoso, ya que creo que puede llevar algo más de tiempo codificar algo (y eso es lo que ven los contadores de frijoles), pero es un "dolor" a corto plazo para la ganancia a largo plazo. Luego tiene (afortunadamente) un código bien probado y probado, con el mecanismo establecido para detectar errores en el futuro cuando las cosas cambian.
Para cualquiera que no esté convencido, dale a TDD por ejemplo una lectura y pruébalo para una iteración de tu software.
Muchas prácticas de codificación toman ... práctica.
Puede aprender y comprender el concepto de programación OO en pocas horas. Pero muchos programadores admitirán que fue solo después de practicar la programación OO durante aproximadamente 2 años que de repente se sintieron "fluidos".
Un programador de C ++ puede "aprender C #" fácilmente en cuestión de días. Pero todavía es muy útil antes de que sean "fluidos" y entiendan todas las implicaciones de todo lo que escriben (en lugar de ser un programador de C ++ que convierte la sintaxis en C #).
Originalmente aprendí a escribir de la manera "dos dedos". Esto avanzó hasta el punto en que pude escribir bastante rápido con este método, pero decidí intentar aprender a escribir al tacto. Durante varias semanas me obligué a soportar el dolor y la frustración de tener que escribir todo muy despacio mediante la función de mecanografía. Fue difícil, y requirió un compromiso real porque con cada línea que escribí solo quería resolverlo con la forma en que ya lo sabía, la forma en que me daría resultados rápidos. Pero finalmente mi velocidad de tipeo táctil coincidió con mi tipeo de dos dedos.
Resistí las convenciones de prefijo de MFC (por ejemplo, los prefijos "m_" y "p") cuando comencé a trabajar con MFC. Parecía un tipeo extra feo, ridículo e inútil. Luego me obligué a usar este sistema por un mes y después de este tiempo no pude entender cómo había escrito el código sin esta convención de nomenclatura, me ayudó a entender el código mejor y más rápido, y redujo el número de bichos tontos.
Entonces, ¿cómo desarrollas la disciplina para hacer TDD? Solo comprométete a hacer TDD por un mes. Será lento. Sera dificil. Será tentador simplemente sacar algunas líneas "a la vieja usanza". Pero después de un tiempo acumularás experiencia y velocidad, y será mucho más fácil y natural trabajar de esta manera. Y luego puede evaluar TDD y no TDD y decidir qué enfoque funciona mejor. Probablemente no mirarás hacia atrás.
TDD es realmente una buena práctica (pero al mismo tiempo, no creo que debamos tratar de lograr una cobertura de código del 100%).
Sus principales ventajas son:
Hace que el desarrollador piense en la API porque necesita usar esa API primero para escribir pruebas. En este paso es muy fácil sentir que algo está mal con su API (los nombres de métodos incorrectos, para muchas líneas son necesarios para las operaciones más comunes, demasiadas excepciones comprobadas impares o, por el contrario, el usuario no tiene posibilidad de manejar excepciones presumibles). Y puedes mejorarlo y cambiarlo como quieras porque nadie lo ha usado todavía.
Piensas en cómo deberían funcionar tus métodos. Esto a menudo abre algunos problemas implícitos o malentendidos en los primeros pasos.
Cuando tiene pruebas, tiene una buena manera de medir el porcentaje de trabajo completado (es decir, si tiene 20 pruebas y se pasan 15 de ellas, entonces se termina el 75% del trabajo). Es más importante para usted como desarrollador que para su equipo o proceso. Solo divide la tarea completa en muchas tareas más pequeñas (por ejemplo, 20) y puede competir una tras otra. Es mucho más agradable que abordar todo.
Las pruebas te permiten jugar con el código. Puede refactorizar, puede mejorar el rendimiento, etc. Y nuevamente, incluso si no lo hace de todos modos, es muy bueno darse cuenta de que tiene la posibilidad de hacerlo. Es un poco de confianza que todo está bien.
¿Cómo hacerse para hacer TDD? ¡No necesitas! Si desea obtener todos los beneficios enumerados, entonces no se hará a sí mismo; solo hará TDD con placer y por libre voluntad. Si no necesita / desea / no puede obtenerlos, no lo haga ahora.
TDD no se trata tanto de escribir pruebas primero. Si todo lo que quiere es escribir sus pruebas primero, entonces quiere la Técnica de Prueba Primero. El problema es que la técnica de Prueba Primero en el vacío (sin TDD) termina descomponiéndose en algo que es casi peor que no tener ninguna prueba en absoluto.
Usted dijo cuál era su problema usted mismo :
o durante el curso del proyecto, se olvida TDD en un esfuerzo por terminar los códigos más rápido
Sin embargo, si estuvieras haciendo TDD, y reconociendo todo el valor que tenía para ofrecer, tu equipo entendería que es imposible obtener un código más rápido sin TDD, ya que es lo que hace que el proceso de programación sea rápido en primer lugar.
Mi sugerencia es dedicar algo de tiempo a entender el valor que puede darle al reconocer los tipos de artefactos que una buena prueba puede reemplazar. Con True TDD, un documento único cumple con todos los siguientes roles / necesidades:
- Prueba (¿esto funciona o no?)
- Análisis (¿qué estamos tratando de lograr?)
- Diseño (¿cómo lo vamos a lograr?)
- Especificación (¿cómo sabremos cuando hayamos terminado?)
- Finish-line (hey, ¡hemos terminado!)
- Informe de progreso (hey, ¿ya terminaron?)
- Control de proceso (¿qué debo hacer después?)
...etcétera. En mi opinión, comprometerse a aprender TDD, que es una disciplina difícil y requerirá mucha práctica para dominar, requiere una comprensión clara del premio real que se encuentra al final del recorrido.
Una vez que tenga esas cosas claramente en mente, puede comenzar a preocuparse por cómo hacer TDD.
TDD se trata de saber lo que estás haciendo y lo que has hecho. Si tengo una configuración TDD adecuada, entonces puedo comentar alguna línea de código que tal vez no sea necesaria y luego ejecutar inmediatamente las pruebas y averiguar si realmente fue necesario si se rompieron las pruebas o no se rompieron las pruebas. Esas pruebas de ruptura deberían contener una descripción suficiente para poder entender por qué esta línea de código era necesaria.
Sin TDD identificar qué se rompe cuando se cambia el código requiere pruebas de regresión humana potencialmente masivas antes de estar seguro de que no ha roto algo. El objetivo de TDD, al igual que con todas las partes de Total Quality Management, es eliminar la mayoría, si no todas, las costosas pruebas manuales al final de la línea de productos. ¿Cómo? Al saber lo que estás haciendo. ¿Cómo? Al medir lo que estás haciendo y estudiar cómo mejorarlo.
Si descubres un error en tu código y lo corrige. Las preguntas deberían ser: ¿cómo sucedió? ¿Puedo evitar que esto suceda en el futuro? ¿Cómo?
Esto puede deberse a requisitos deficientes. Esto puede deberse a factores fuera de su control. La clave es no solo cepillar los problemas debajo de la alfombra, sino tratar de comprender y sacar el conocimiento de cómo hacerlo e incorporarlo en sus procesos.
TDD es solo una parte de esto y no funcionará bien sin un entorno compatible y alentador.
Para lograr esto, la gerencia necesita comprar el principio básico de que los métodos ágiles abaratan los cambios a largo plazo. Con métodos ágiles, el costo del cambio aumenta logarítmicamente, mientras que el desarrollo sin métodos ágiles hace que el costo de los cambios aumente exponencialmente con el tiempo.
Hay mucho más para leer sobre esto. Google el siguiente "William Edward Deming", "Gestión de calidad total", "Curva de costo de cambio".