que practices practice paper creador ciclo language-agnostic tdd

language agnostic - practices - ¿Qué tan estricto debería ser en el "hacer lo más simple que podría funcionar" mientras hago TDD



tdd practice (7)

Para TDD tienes que

  1. Crea una prueba que falle.
  2. Haz lo más simple que puedas trabajar para pasar la prueba.
  3. Añadir más variantes de la prueba y repetir.
  4. Refactorizar cuando emerge un patrón.

Con este enfoque, se supone que debe cubrir todos los casos (al menos eso me viene a la mente), pero me pregunto si estoy siendo demasiado estricto aquí y si es posible "anticipar" algunos escenarios en lugar de simplemente descubrirlos .

Por ejemplo, estoy procesando un archivo y, si no se ajusta a un determinado formato, debo lanzar una InvalidFormatException

Así que mi primera prueba fue:

@Test void testFormat(){ // empty doesn''t do anything nor throw anything processor.validate("empty.txt"); try { processor.validate("invalid.txt"); assert false: "Should have thrown InvalidFormatException"; } catch( InvalidFormatException ife ) { assert "Invalid format".equals( ife.getMessage() ); } }

Lo ejecuto y falla porque no lanza una excepción.

Así que lo siguiente que me viene a la mente es: "Haz lo más simple que pueda funcionar" , así que:

public void validate( String fileName ) throws InvalidFormatException { if(fileName.equals("invalid.txt") { throw new InvalidFormatException("Invalid format"); } }

Doh !! ( aunque el código real es un poco más complicado, me encontré haciendo algo así varias veces )

Sé que eventualmente debo agregar otro nombre de archivo y otra prueba que haga que este enfoque sea poco práctico y que me obligue a refactorizar algo que tenga sentido (que si entendí correctamente es el punto de TDD, descubrir los patrones de uso). revela) pero

P: ¿ Estoy tomando literalmente las cosas de "Hacer la cosa más simple ..." ?


Al igual que un método debe hacer solo una cosa, una prueba debe probar solo una cosa (comportamiento). Para abordar el ejemplo dado, escribiría dos pruebas, por ejemplo, test_no_exception_for_empty_file y test_exception_for_invalid_file . De hecho, la segunda podría ser varias pruebas, una por tipo de invalidez.

El tercer paso del proceso de TDD se interpretará como "agregar una nueva variante de la prueba", no "agregar una nueva variante a la prueba". De hecho, una prueba unitaria será atómica (solo una prueba) y generalmente sigue el patrón triple A: Organizar - Actuar - Afirmar. Y es muy importante verificar que la prueba falle primero, para asegurarse de que realmente esté probando algo.

También separaría la responsabilidad de leer el archivo y validar su contenido. De esa manera, la prueba puede pasar un búfer a la función validate (), y las pruebas no tienen que leer los archivos. Por lo general, las pruebas unitarias no acceden al sistema de archivos porque esto las ralentiza.


Creo que tu enfoque está bien, si te sientes cómodo con él. No perdió el tiempo escribiendo un caso tonto y resolviéndolo de una manera tonta: escribió una prueba seria para la funcionalidad deseada real y la hizo pasar, como usted dice, la forma más sencilla que podría funcionar. Ahora, y en el futuro, a medida que agregue más y más funcionalidad real, se asegura de que su código tenga el comportamiento deseado de lanzar la excepción correcta en un archivo en particular mal formateado. Lo que viene después es hacer que ese comportamiento sea real, y puede conducirlo escribiendo más pruebas. Cuando se vuelve más sencillo escribir el código correcto que falsificarlo de nuevo, ahí es cuando escribirá el código correcto. Esa evaluación varía entre los programadores y, por supuesto, algunos decidirían que es cuando se escribe la primera prueba que falla.

Estás usando pasos muy pequeños, y ese es el enfoque más cómodo para mí y para algunos otros TDDers. Si te sientes más cómodo con los pasos más grandes, también está bien, pero debes saber que siempre puedes recurrir a un proceso más preciso en esas ocasiones en que los grandes pasos te hacen tropezar.


Muchos comentarios:

  • Si la validación de "empty.txt" lanza una excepción, no la atrapa.

  • No te repitas. Debe tener una única función de prueba que decida si la validación produce o no la excepción. Luego llame a esa función dos veces, con dos resultados esperados diferentes.

  • No veo ningún signo de un marco de prueba de unidad. Tal vez los estoy extrañando? Pero solo usar assert no se escalará a sistemas más grandes. Cuando obtiene un resultado de la validación, debe tener una forma de anunciar a un marco de prueba que una prueba determinada, con un nombre dado, tuvo éxito o fracasó.

  • Estoy alarmado por la idea de que verificar un nombre de archivo (en lugar de contenido ) constituye una "validación". En mi opinión, eso es un poco demasiado simple.

Con respecto a su pregunta básica, creo que se beneficiaría de una idea más amplia de lo que es lo más simple. Tampoco soy un TDDer fundamentalista, y estaría bien si te permitiera "pensar por adelantado" un poco . Esto significa pensar con anticipación para esta tarde o mañana por la mañana, y no pensar con anticipación para la próxima semana.


Por supuesto, tu interpretación de la regla es demasiado literal. Probablemente debería sonar como "Haz lo más simple potencialmente útil ..."

Además, creo que al escribir la implementación, debe olvidar el cuerpo de la prueba que está tratando de satisfacer. Debe recordar solo el nombre de la prueba (que debe informarle sobre lo que realiza la prueba). De esta manera, se verá obligado a escribir el código lo suficientemente genérico como para ser útil.


Te perdiste el punto # 0 en tu lista: sabe qué hacer. Usted dice que está procesando un archivo para fines de validación. Una vez que haya especificado qué significa "validación" (sugerencia: haga esto antes de escribir cualquier código), podría tener una mejor idea de cómo a) escribir pruebas que, bueno, probar la especificación como se implementó, yb) escribir la cosa más simple .

Si, por ejemplo, la validación es "debe ser XML", su caso de prueba es solo una cadena no compatible con xml, y su implementación está utilizando una biblioteca XML y (si es necesario) transforma sus excepciones en aquellas especificadas para su función de "validación" .


Una cosa a tener en cuenta para los futuros estudiantes de TDD: el mantra de TDD no incluye en realidad "Hacer lo más simple que podría funcionar". El libro de TDD de Kent Beck tiene solo 3 pasos:

  1. Rojo: escriba una pequeña prueba que no funcione, y tal vez ni siquiera compile al principio.
  2. Verde: haga que la prueba funcione rápidamente, cometiendo los pecados necesarios en el proceso.
  3. Refactor: elimine toda la duplicación creada simplemente para que la prueba funcione.

Aunque la frase "Hacer la cosa más simple ..." a menudo se atribuye a Ward Cunningham, en realidad hizo una pregunta: "¿Cuál es la cosa más simple que podría funcionar?" , pero esa pregunta se convirtió más tarde en una orden, que Ward cree que puede confundir más bien ayuda.

Edición: No puedo recomendar leer el libro TDD de Beck con suficiente fuerza, es como tener una sesión de emparejamiento con el maestro mismo, brindándole sus ideas y pensamientos sobre el proceso de desarrollo dirigido por pruebas.


Yo también soy un novato TDD luchando con esta pregunta. Mientras investigaba, encontré esta publicación de blog de Roy Osherove que fue la primera y única definición concreta de "la cosa más simple que podría funcionar" que encontré (e incluso Roy admitió que solo fue un comienzo).

En pocas palabras, Roy dice:

Mire el código que acaba de escribir en su código de producción y pregúntese lo siguiente:

"¿Puedo implementar la misma solución de una manera que sea ..."

  1. ".. Más codificado ..."
  2. "... Más cerca del principio del método en el que lo escribí ..."
  3. ".. Menos sangrado (en el menor número de" ámbitos "posibles como ifs, bucles, try-catch) .."
  4. "... más corto (literalmente, menos caracteres para escribir) y aún así legible ..."

"... y aun así hacer que todas las pruebas pasen?"

Si la respuesta a uno de estos es "sí", entonces haz eso y verás que todas las pruebas pasan.