Pregunta

He leído varios libros y sitios web sobre el tema de TDD, y todos tienen mucho sentido, especialmente el libro de Kent Beck. Sin embargo, cuando trato de hacer TDD yo mismo, me encuentro mirando el teclado preguntándome cómo empezar. ¿Hay algún proceso que uses? ¿Cuál es tu proceso de pensamiento? ¿Cómo identificas tus primeras pruebas?

La mayoría de los libros sobre el tema hacen un buen trabajo al describir qué es TDD, pero no cómo practicar TDD en aplicaciones reales no triviales. ¿Cómo haces TDD?

¿Fue útil?

Solución

Solía ??tener el mismo problema. Solía ??comenzar la mayor parte del desarrollo iniciando un diseñador de ventanas para crear la interfaz de usuario para la primera característica que quería implementar. Como la interfaz de usuario es una de las cosas más difíciles de probar, esta forma de trabajar no se traduce muy bien en TDD.

Encontré los documentos de objetos atómicos en Presenter First muy útiles. Todavía empiezo imaginando acciones de usuario que quiero implementar (si tiene casos de uso, esa es una excelente manera de comenzar) y utilizando un modelo MVP o MVC-ish, comienzo con la escritura de una prueba para el presentador de la primera pantalla. Al burlarse de la vista hasta que el presentador funcione, puedo comenzar muy rápido de esta manera. http://www.atomicobject.com/pages/Presenter+First aquí hay más información trabajando de esta manera.

Si está comenzando un proyecto en un lenguaje o marco desconocido para usted o tiene muchos desconocidos, puede comenzar haciendo un pico primero. A menudo también escribo pruebas unitarias para mis picos, pero solo para ejecutar el código que estoy piqueando. Hacer el pico puede brindarle información sobre cómo iniciar su proyecto real. No olvide tirar su espiga cuando comience con su proyecto real

Otros consejos

Es más fácil de lo que piensas, en realidad. Simplemente usa TDD en cada clase individual. Cada método público que tenga en la clase debe ser probado para todos los resultados posibles. Entonces la "prueba de concepto" Los ejemplos de TDD que ve también se pueden usar en una aplicación relativamente grande que tiene muchos cientos de clases.

Otra estrategia TDD que podría utilizar es simular las ejecuciones de prueba de la aplicación, encapsulando el comportamiento principal de la aplicación. Por ejemplo, he escrito un marco (en C ++, pero esto debería aplicarse a cualquier lenguaje OO) que represente una aplicación. Hay clases abstractas para la inicialización, el runloop principal y el cierre. Así que mi método main () se parece a esto:

int main(int argc, char *argv[]) {
  int result = 0;

  myApp &mw = getApp(); // Singleton method to return main app instance
  if(mw.initialize(argc, argv) == kErrorNone) {
    result = mw.run();
  }

  mw.shutdown();
  return(result);
}

La ventaja de hacer esto es doble. En primer lugar, toda la funcionalidad de la aplicación principal se puede compilar en una biblioteca estática, que luego se vincula con el conjunto de pruebas y este archivo stub main.cpp. En segundo lugar, significa que puedo simular todas las " ejecuciones " de la aplicación principal mediante la creación de matrices para argc & amp; argv [], y luego simulando lo que sucedería en main (). Utilizamos este proceso para probar muchas funcionalidades del mundo real para asegurarnos de que la aplicación genere exactamente lo que se supone que debe hacer, dado un cierto cuerpo real de datos de entrada y argumentos de la línea de comandos.

Ahora, probablemente se esté preguntando cómo cambiaría esto para una aplicación que tiene una GUI real, una interfaz basada en la web o lo que sea. Para eso, simplemente diría que use maquetas para probar estos aspectos del programa.

Pero en resumen, mi consejo se reduce a esto: desglosa tus casos de prueba al nivel más pequeño, luego comienza a mirar hacia arriba. Eventualmente, el conjunto de pruebas los unirá a todos, y terminará con un nivel razonable de cobertura de pruebas automatizadas.

Comienzo con el pensamiento de los requisitos.

foreach UseCase

  1. analizar UseCase
  2. piensa en las clases futuras
  3. escribir casos de prueba
  4. pruebas de escritura
  5. prueba e implementación de clases (a veces agregando nuevas pruebas si me perdí algo en el punto 4).

Eso es todo. Es bastante simple, pero creo que consume mucho tiempo. Aunque me gusta y me atengo a ella. :)

Si tengo más tiempo, trato de modelar algunos diagramas secuenciales en Enterprise Architect.

Estoy de acuerdo en que es especialmente difícil iniciar el proceso.

Normalmente trato de pensar en el primer conjunto de pruebas como un guión de película, y tal vez solo la primera escena de la película.

  

El actor1 le dice al actor2 que el mundo es   En problemas, Actor2 devuelve un   paquete, Actor1 desempaqueta el paquete,   etc.

Este es obviamente un ejemplo extraño, pero a menudo me parece que visualizar las interacciones es una buena forma de superar esa joroba inicial. Existen otras técnicas análogas (historias de usuarios, tarjetas RRC, etc.) que funcionan bien para grupos más grandes, pero parece que usted está solo y es posible que no necesite la sobrecarga adicional.

También, estoy seguro de que lo último que quieres hacer es leer otro libro, pero los chicos de MockObjects.com tienen un libro en las primeras etapas del borrador, actualmente titulado Software orientado a objetos en crecimiento, guiado por pruebas . Los capítulos que se encuentran actualmente en revisión pueden ofrecerle más información sobre cómo iniciar TDD y continuarla en todo momento.

El problema es que estás mirando tu teclado preguntándote qué pruebas necesitas escribir.

En su lugar, piense en el código que desea escribir, luego busque la primera parte pequeña de ese código, luego intente pensar en la prueba que lo obligaría a escribir esa pequeña porción de código.

Al principio, ayuda trabajar en muy piezas pequeñas. Incluso en el transcurso de un solo día, trabajará en trozos más grandes. Pero cada vez que se atasque, piense en el código más pequeño que desea escribir a continuación, luego escriba la prueba para ello.

No creo que realmente deba comenzar con TDD. En serio, ¿dónde están tus especificaciones? ¿Ya ha acordado un diseño general general o aproximado para su sistema, que puede ser apropiado para su aplicación? Sé que TDD y Agile desalientan a Big Design Up-Front, pero eso no significa que no debas hacer Design Up-Front primero antes de TDD a través de la implementación de ese diseño.

A veces no sabes cómo hacer TDD porque tu código no es " amigable para las pruebas " (fácilmente verificable).

Gracias a algunas buenas prácticas, sus clases pueden ser más fáciles de evaluar de forma aislada, para lograr verdaderas pruebas de unidad.

Hace poco me encontré con un blog de un empleado de Google, que describe cómo puede diseñar sus clases y métodos para que sean más fáciles de probar.

Aquí está una de sus conversaciones recientes que recomiendo.

Insiste en el hecho de que debe separar la lógica empresarial del código de creación de objetos (es decir, para evitar mezclar la lógica con el operador 'nuevo'), utilizando el patrón de Inyección de dependencias. También explica cómo la Ley de Demeter es importante para el código comprobable. Se centra principalmente en el código Java (y Guice ) pero sus principios deberían aplicarse a cualquier El lenguaje realmente.

Lo más fácil es comenzar con una clase que no tenga dependencias, una clase que es usada por otras clases, pero que no usa otra clase. Entonces deberías realizar una prueba y preguntarte "¿cómo sabría si esta clase (este método) se implementa correctamente?".

Luego, puede escribir una primera prueba para interrogar su objeto cuando no está inicializado, podría devolver NULL o lanzar una excepción. Luego puede inicializar (quizás solo parcialmente) su objeto, y probarlo devuelve algo valioso. Luego puede agregar una prueba con otro valor de inicialización, debe comportarse de la misma manera. En ese momento, generalmente pruebo una condición de error, como intentar inicializar el objeto con un valor no válido.

Cuando haya terminado con el método, vaya a otro método de la misma clase hasta que haya terminado con toda la clase.

Luego puedes elegir otra clase, ya sea otra clase independiente o una clase que use la primera clase que hayas implementado.

Si va con una clase que se basa en su primera clase, creo que es aceptable tener su entorno de prueba, o su segunda clase, instanciar la primera clase, ya que se ha probado completamente. Cuando falla una prueba sobre la clase, debe poder determinar en qué clase se encuentra el problema.

Si descubre un problema en la primera clase, o pregunta si se comportará correctamente bajo ciertas condiciones particulares, escriba una nueva prueba.

Si escalas las dependencias crees que las pruebas que estás escribiendo abarcan muchas clases para ser calificadas como pruebas unitarias, entonces puedes usar un objeto simulado para aislar una clase del resto del sistema.


Si ya tiene su diseño, como indicó en un comentario en la respuesta de Jon LimJap, entonces no está haciendo TDD puro, ya que TDD trata sobre el uso de pruebas unitarias para que surja su diseño.

Dicho esto, no todas las tiendas permiten TDD estricto, y tienes un diseño a mano, así que usémoslo y hagamos TDD, aunque sería mejor decir Test-First-Programming, pero ese no es el punto, ya que ese es el punto. También cómo comencé TDD.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top