El ciclo Rojo - Verde - Refactor para TDD está bien establecido y aceptado. Escribimos una prueba de unidad que falla y la hacemos pasar de la manera más simple posible. ¿Cuáles son los beneficios de este enfoque sobre escribir muchas pruebas unitarias reprobadas para una clase y hacer que todas pasen de una vez?
El conjunto de pruebas aún lo protege contra escribir código incorrecto o cometer errores en la etapa de refactorización, entonces, ¿cuál es el daño? A veces es más fácil escribir todas las pruebas para una clase (o módulo) primero como una forma de 'descarga de cerebro' para escribir rápidamente todo el comportamiento esperado de una sola vez.
Respuestas:
El diseño basado en pruebas se trata de hacer que su API sea correcta, no el código.
El beneficio de escribir primero las pruebas de fallas más simples es que obtienes tu API (que esencialmente es que estás diseñando sobre la marcha) lo más simple posible. En la delantera.
Cualquier uso futuro (que son las próximas pruebas que escriba) irá desde el diseño simple inicial, en lugar de un diseño subóptimo frente a casos más complejos.
fuente
Cuando escribes una prueba, te concentras en una cosa.
Con muchas pruebas, concentra su atención en muchas tareas, por lo que no es una buena idea.
fuente
Una de las dificultades al escribir pruebas unitarias es que está escribiendo código, y eso en sí mismo puede ser propenso a errores. También existe la posibilidad de que termine necesitando cambiar sus pruebas más adelante como resultado de un esfuerzo de refactorización a medida que escribe su código de implementación. Con TDD, esto significa que podría terminar llevándose un poco demasiado lejos con sus pruebas y encontrando que necesita reescribir una gran cantidad de código de prueba esencialmente "no probado" a medida que su implementación madura en el transcurso del proyecto. Una forma de evitar este tipo de problema es simplemente enfocarse en hacer una sola cosa a la vez. Esto asegura que minimice el impacto de cualquier cambio en sus pruebas.
Por supuesto, esto se reducirá en gran medida a cómo escribir su código de prueba. ¿Está escribiendo una prueba unitaria para cada método individual, o está escribiendo pruebas que se centran en características / requisitos / comportamientos? Otro enfoque podría ser utilizar un enfoque basado en el comportamiento con un marco adecuado y centrarse en escribir pruebas como si fueran especificaciones. Esto significaría adoptar el método BDD o adaptar las pruebas BDD si desea seguir con TDD más formalmente. Alternativamente, puede seguir completamente con el paradigma TDD, pero alterar la forma en que escribe las pruebas para que, en lugar de centrarse por completo en los métodos de prueba individualmente, pruebe los comportamientos de manera más general como un medio para satisfacer los detalles de las características de requisitos que está implementando.
Independientemente del enfoque específico que adopte, en todos los casos que he descrito anteriormente, está utilizando un enfoque de prueba primero, por lo que si bien puede ser tentador simplemente descargar su cerebro en un conjunto de pruebas encantador, también desea luchar contra el La tentación de hacer más de lo absolutamente necesario. Cada vez que estoy a punto de comenzar un nuevo conjunto de pruebas, comienzo a repetirme YAGNI y, a veces, incluso lo incluyo en un comentario en mi código para recordarme que me mantenga enfocado en lo que es inmediatamente importante y que solo haga el mínimo requerido para satisfacer el requisitos de la función que estoy a punto de implementar. Cumplir con Red-Green-Refactor ayuda a garantizar que lo haga.
fuente
Creo que al hacer esto, se pierde el proceso de TDD. Simplemente escribiendo todas sus pruebas al principio, realmente no está pasando por el proceso de desarrollo utilizando TDD. Simplemente está adivinando por adelantado qué pruebas necesitará. Este será un conjunto de pruebas muy diferente de las que terminas escribiendo si las haces una a la vez a medida que desarrollas tu código. (A menos que su programa sea trivial por naturaleza).
fuente
Sí "escribo" todas las pruebas que puedo pensar por adelantado mientras hago "tormenta de ideas", sin embargo, escribo cada prueba como un solo comentario que describe la prueba.
Luego convierto una prueba a código y hago el trabajo para que se compile y pase . A menudo decido que no necesito todas las pruebas que pensé que necesitaba, o necesito diferentes pruebas, esta información solo proviene de escribir el código para que las pruebas pasen.
El problema es que no puede escribir una prueba en el código hasta que haya creado el método y las clases que prueba, de lo contrario solo obtendrá muchos errores del compilador que le ayudarán a trabajar en una sola prueba a la vez.
Ahora, si está utilizando un sistema como flujo de especificaciones cuando las pruebas están escritas en "inglés", es posible que desee que los clientes acepten un conjunto de pruebas mientras tiene su tiempo, en lugar de crear una sola prueba.
fuente
La idea detrás de TDD es iteraciones rápidas.
Si tiene grandes extensiones de pruebas que deben escribirse antes de tener que escribir su código, es difícil refactorizarlo de forma iterativa.
Sin una fácil refactorización del código, pierde muchos de los beneficios de TDD.
fuente
En mi experiencia (limitada) con TDD, puedo decirle que cada vez que he roto la disciplina de escribir un examen a la vez, las cosas han ido mal. Es una trampa fácil para caer. "Oh, ese método es trivial", piensas para ti mismo, "así que simplemente eliminaré estas otras dos pruebas relacionadas y seguiré adelante". ¿Bien adivina que? Nada es tan trivial como parece. Cada vez que caí en esta trampa, terminé depurando algo que pensé que era fácil, pero resultó tener extraños casos de esquina. Y desde que escribí varias pruebas a la vez, fue mucho trabajo rastrear dónde estaba el error.
Si necesita un volcado de información del cerebro, tiene muchas opciones:
Tenga en cuenta que en ninguna parte de esta lista está el compilador. :-)
fuente
Está asumiendo que sabe cómo se verá su código antes de escribirlo. TDD / BDD es tanto un proceso de diseño / descubrimiento como un proceso de control de calidad. Para una característica dada, usted escribe la prueba más simple que verificaría que la característica está satisfecha (a veces esto puede requerir varias debido a la complejidad de una característica). La primera prueba que escriba está cargada de suposiciones de cómo se verá el código de trabajo. Si escribe todo el conjunto de pruebas antes de escribir la primera línea de código para admitirlo, está haciendo una gran cantidad de suposiciones no verificadas. En cambio, escriba una suposición y verifíquela. Luego escribe el siguiente. En el proceso de verificación de la siguiente suposición, es posible que rompa una suposición anterior para tener que retroceder y cambiar esa primera suposición para que coincida con la realidad o cambiar la realidad para que esa primera suposición aún se aplique.
Piense en cada prueba unitaria que escriba como una teoría en un cuaderno científico. A medida que llena el cuaderno, prueba sus teorías y forma otras nuevas. A veces, probar una nueva teoría refuta una teoría anterior, por lo que debe corregirla. Es más fácil demostrar una teoría a la vez en lugar de intentar decir 20 a la vez.
fuente
TDD es un enfoque altamente iterativo, que (en mi experiencia) se adapta mejor a las formas de desarrollo del mundo real. Por lo general, mi implementación toma forma gradualmente durante este proceso, y cada paso puede traer más preguntas, ideas e ideas para la prueba. Esto es ideal para mantener mi mente enfocada en la tarea real, y es muy eficiente porque solo necesito mantener un número limitado de cosas en la memoria a corto plazo en cualquier momento. Esto a su vez reduce la posibilidad de errores.
Su idea es básicamente un enfoque Big Test Up Front, que en mi humilde opinión es más difícil de manejar y puede ser más derrochador. ¿Qué sucede si se da cuenta a mitad de su trabajo de que su enfoque no es bueno, su API es defectuosa y necesita comenzar de nuevo, o usar una biblioteca de terceros? Entonces, una gran parte del trabajo realizado al escribir sus exámenes por adelantado se convierte en un esfuerzo inútil.
Dicho esto, si esto funciona para ti, está bien. Me imagino que si trabaja desde una especificación técnica fija y detallada, en un dominio con el que tiene experiencia íntima y / o en una tarea bastante pequeña, puede tener la mayoría o todos los casos de prueba necesarios listos y su implementación clara desde el comienzo. Entonces podría tener sentido comenzar escribiendo todas las pruebas a la vez. Si su experiencia es que esto lo hace más productivo a largo plazo, no necesita preocuparse demasiado por los libros de reglas :-)
fuente
Más allá de solo pensar en una cosa, un paradigma de TDD es escribir el menor código posible para pasar la prueba. Cuando escribe una prueba a la vez, es mucho más fácil ver la ruta para escribir el código suficiente para pasar esa prueba. Con un conjunto completo de pruebas para pasar, no se llega al código en pequeños pasos, sino que se debe dar un gran salto para que todos pasen de una vez.
Ahora, si no se limita a escribir el código para que todos pasen "de una vez", sino que escriba el código suficiente para pasar una prueba a la vez, aún podría funcionar. Sin embargo, tendría que tener más disciplina para no solo seguir adelante y escribir más código del que necesita. Una vez que comienzas por ese camino, te dejas abierto a escribir más código del que describen las pruebas, lo que puede no probarse , al menos en el sentido de que no es conducido por una prueba y tal vez en el sentido de que no es necesario (o ejercido) por cualquier prueba.
Entender qué debe hacer el método, como comentarios, historias, una especificación funcional, etc., es perfectamente aceptable. Sin embargo, esperaría traducir esto en pruebas de una en una.
La otra cosa que puede perderse al escribir las pruebas de una vez es el proceso de pensamiento por el cual pasar una prueba puede incitarlo a pensar en otros casos de prueba. Sin un banco de pruebas existentes, debe pensar en el próximo caso de prueba en el contexto de la última prueba aprobada. Como dije, tener una buena idea de lo que se supone que debe hacer el método es muy bueno, pero muchas veces me he encontrado encontrando nuevas posibilidades que no había considerado a priori, pero que solo ocurrieron en el proceso de escribir el pruebas Existe el peligro de que pueda omitirlos a menos que tenga el hábito específico de pensar qué pruebas nuevas puedo escribir que aún no tengo.
fuente
Trabajé en un proyecto donde los desarrolladores que escribieron las pruebas (fallidas) eran diferentes de los desarrolladores que implementaron el código necesario para hacerlos pasar y lo encontré realmente efectivo.
En ese caso, solo las pruebas relacionadas con la iteración actual se escribieron una vez. Entonces, lo que sugieres es perfectamente posible en ese tipo de escenario.
fuente
fuente
El ciclo Rojo-Verde-Refactor es una lista de verificación destinada a desarrolladores nuevos en TDD. Diría que es una buena idea seguir esta lista de verificación hasta que sepa cuándo seguirla y cuándo puede romperla (es decir, hasta que sepa no tiene que hacer esta pregunta en stackoverflow :)
Después de haber realizado TDD durante casi una década, puedo decirle que rara vez, si alguna vez, escribo muchas pruebas fallidas antes de escribir el código de producción.
fuente
Está describiendo BDD, donde algún interesado externo tiene una especificación ejecutable. Esto puede ser beneficioso si hay una especificación inicial predeterminada (por ejemplo, una especificación de formato, estándar industrial o donde el programador no es el experto en el dominio).
El enfoque normal es cubrir gradualmente más y más pruebas de aceptación, que es el progreso visible para el gerente del proyecto y el cliente.
Por lo general, tiene estas pruebas especificadas y ejecutadas en un marco BDD como Cucumber, Fitnesse o algo así.
Sin embargo, esto no es algo que mezcle con sus pruebas unitarias, que están mucho más cerca de los detalles de implementación esenciales con una gran cantidad de casos límite relacionados con API, problemas de inicialización, etc., muy centrados en el elemento bajo prueba , que es un artefacto de implementación .
La disciplina del refactor rojo-verde tiene muchos beneficios, y la única ventaja que puede esperar al escribirlos desde el principio es alcanzar el punto de equilibrio.
fuente
Una prueba a la vez: la principal ventaja es centrarse en una cosa. Piense en un diseño profundo: puede profundizar y mantenerse enfocado con un ciclo de retroalimentación rápido. ¡Sin embargo, puede perder el alcance de todo el problema! Ese es el momento en que entra en juego la refactorización (grande). Sin ella, TDD no funciona.
Todas las pruebas: el análisis y el diseño pueden revelarle más sobre el alcance del problema. Piense en un diseño amplio primero. Usted analiza el problema desde más ángulos y agrega información de la experiencia. Es intrínsecamente más difícil, pero puede generar beneficios interesantes, menos refactorización, si hace 'lo suficiente'. ¡Cuidado, es fácil analizar en exceso y, sin embargo, errar por completo!
En general, me resulta difícil recomendar uno u otro, porque los factores son muchos: experiencia (especialmente con el mismo problema), conocimiento y habilidades de dominio, amabilidad del código para la refactorización, complejidad del problema ...
Supongo que si nos enfocamos más estrechamente en las aplicaciones comerciales típicas, entonces TDD con su enfoque rápido de prueba y error generalmente ganaría en términos de efectividad.
fuente
Suponiendo que su marco de prueba lo admite, lo que sugeriría es que, en lugar de implementar las pruebas que desea realizar braindump, escriba pruebas pendientes descriptivas que luego implementará. Por ejemplo, si su API debe hacer foo and bar pero no biz, simplemente agregue el siguiente código (este ejemplo está en rspec) para su conjunto de pruebas, luego atacarlos uno por uno. Tienes tus pensamientos rápidamente y puedes abordar todos tus problemas uno por uno. Cuando pasen todas las pruebas, sabrá cuándo ha abordado todos los problemas que tuvo durante su braindump.
fuente