2008-10-17 8 views
15

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, me encuentro mirando el teclado preguntándome cómo comenzar. ¿Hay algún proceso que uses? ¿Cuál es tu proceso de pensamiento? ¿Cómo identifica sus primeras pruebas?¿Cómo se hace TDD en una aplicación no trivial?

La mayoría de los libros sobre el tema hacen un gran trabajo describiendo qué es TDD, pero no cómo práctica TDD en aplicaciones no triviales del mundo real. ¿Cómo se hace TDD?

Respuesta

4

Yo solía tener el mismo problema. Solía ​​comenzar la mayoría 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 Presentador Primero muy útiles. Todavía comienzo visualizando las acciones de los usuarios que deseo implementar (si tienes un caso de uso que es una gran manera de comenzar) y usando un modelo MVP o MVC-ish, comienzo a escribir una prueba para el presentador de la primera pantalla. Al burlar la vista hasta que el presentador funcione, puedo comenzar realmente rápido de esta manera. http://www.atomicobject.com/pages/Presenter+First aquí hay más información sobre cómo trabajar de esta manera.

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

+1

Por favor, podría explicar qué significa "hacer una espiga". No he encontrado la terminación antes. Presumiblemente, ¿te refieres a un prototipo? – Ben

+1

Spike proviene de XP (programación extrema), un pico es más pequeño que un prototipo (mis picos suelen tardar de media hora a una hora). Significa escribir código desechable para probar una pequeña pieza de tecnología.Como no está escribiendo código de producción, puede hacer picos sin probar y refactorizar. – Mendelt

3

Empiezo por pensar en los requisitos.

USECASE foreach

  1. analizar USECASE
  2. pensar en futuras clases
  3. escribir casos de prueba
  4. pruebas de escritura
  5. prueba e implementación de clases (a veces añadiendo nuevas pruebas si echaba de menos algo en punto 4).

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

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

0

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

+0

No dije comenzar con TDD, dije cómo se hace TDD. Tengo especificaciones Tengo diseños conceptuales. Tengo casos de uso. Pero cuando aparece la codificación, ¿dónde empiezas? Claro, podría escribir un montón de pruebas aleatorias para objetos aleatorios, pero eso realmente no trae ninguna cohesión. –

5

Es más fácil de lo que cree, en realidad. Simplemente usa TDD en cada clase individual. Todos los métodos públicos que tenga en la clase deben probarse para ver todos los resultados posibles. Por lo tanto, los ejemplos TDD de "prueba de concepto" que ve también se pueden usar en una aplicación relativamente grande que tiene muchos cientos de clases.

Otra estrategia de TDD que podría usar es simular las ejecuciones de pruebas de aplicación, al encapsular el comportamiento de la aplicación principal.Por ejemplo, he escrito un marco (en C++, pero esto debería aplicarse a cualquier lenguaje OO) que representa una aplicación. Hay clases abstractas para la inicialización, el runloop principal y el apagado. Entonces mi método main() se ve así:

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, todas las funciones principales de la aplicación se pueden compilar en una biblioteca estática, que luego se vincula tanto con el conjunto de pruebas como con el archivo stub main.cpp. En segundo lugar, significa que puedo simular "ejecuciones" completas de la aplicación principal creando matrices para argc & argv [], y luego simulando lo que sucedería en main(). Usamos 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 corpus del mundo real de datos de entrada y argumentos de línea de comandos.

Ahora, probablemente se esté preguntando cómo cambiaría esto para una aplicación que tenga una GUI real, una interfaz basada en la web o lo que sea. Para eso, simplemente diría usar 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 bajo, luego comienza a mirar hacia arriba. Eventualmente, el conjunto de pruebas los juntará a todos y obtendrá un nivel razonable de cobertura de prueba automatizada.

1

Acepto que es especialmente difícil iniciar el proceso.

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

Actor1 dice Actor2 que el mundo está en problemas , Actor2 manos hacia atrás un paquete , Actor1 desempaqueta el paquete, etc.

Eso es, obviamente, un ejemplo extraño, pero a menudo se encuentran la visualización las interacciones son una buena manera de superar esa joroba inicial. Existen otras técnicas análogas (historias de usuario, tarjetas RRC, etc.) que funcionan bien para grupos más grandes, pero parece que estás solo y puede que no necesites la sobrecarga adicional.

Además, estoy seguro de que lo último que desea hacer es leer otro libro, pero los chicos de MockObjects.com tienen un libro en las primeras etapas del borrador, actualmente titulado Growing Object-Oriented Software, Guided by Tests. Los capítulos que se revisan actualmente pueden brindarle más información sobre cómo iniciar TDD y continuarlo durante todo el proceso.

+0

Gracias por la recomendación. Bootstrapping es un buen término. –

1

El problema es que está mirando su teclado preguntándose qué pruebas debe escribir.

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

Al principio, ayuda a trabajar en muy piezas pequeñas. Incluso en el transcurso de un solo día estarás trabajando en trozos más grandes. Pero cada vez que te quedes atascado solo piensas en la pieza de código más pequeña que quieras escribir a continuación, luego escribe la prueba para ello.

0

A veces no sabes cómo hacer TDD porque tu código no es "prueba amigable" (fácilmente comprobable).

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

Recientemente me encontré con un blog por 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.

Here is one of his recent talks que recomiendo.

Insiste en el hecho de que debe separar la lógica de negocio del código de creación de objeto (es decir, para evitar la mezcla de lógica con el operador 'nuevo'), mediante el patrón de Inyección de dependencia. También explica cómo la Ley de Demeter es importante para el código comprobable. Se enfoca principalmente en el código Java (y Guice), pero sus principios deberían aplicarse a cualquier idioma en realidad.

+0

Conversaciones de Miško Hevery son geniales, buena recomendación. – Nazgob

0

Lo más fácil es comenzar con una clase que no tenga dependencias, una clase que sea utilizada por otras clases, pero que no use otra clase. Luego debe tomar una prueba, preguntándose "¿cómo sabría si esta clase (este método) se implementa correctamente?".

Luego podría escribir una primera prueba para interrogar a su objeto cuando no se inicialice, podría devolver NULO o lanzar una excepción. Luego puede inicializar (tal vez solo parcialmente) su objeto, y probar la prueba devuelve algo valioso. Luego puede agregar una prueba con otro valor de inicialización, debe comportarse de la misma manera. En ese momento, suelo probar una condición de error, como intentar inicializar el objeto con un valor no válido.

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

Luego puede elegir otra clase, ya sea otra clase independiente, o clase que use la primera clase que haya implementado.

Si elige una clase que dependa de su primera clase, creo que es aceptable tener su entorno de prueba, o su segunda clase, instanciando la primera clase, ya que se ha probado completamente. Cuando falla una prueba sobre la clase, debe poder determinar en qué clase reside el problema.

En caso de que descubra un problema en la primera clase, o pregunte si se comportará correctamente bajo ciertas condiciones particulares, escriba una nueva prueba.

Si sube las dependencias y cree que las pruebas que está escribiendo abarcan muchas clases para calificar como pruebas unitarias, entonces puede usar un objeto simulado para aislar una clase del resto del sistema.


Si ya tiene el diseño - como usted ha indicado en un comentario en la respuesta de Jon Limjap, entonces no estamos haciendo TDD puro desde TDD es sobre el uso de pruebas de unidad para que su diseño emerger.

Dicho esto, no todas las tiendas permiten un TDD estricto, y usted tiene un diseño a mano, así que utilicémoslo y hagamos TDD, aunque sería mejor decir Prueba-Primero-Programación, pero ese no es el punto, ya que así es también como comencé TDD.

Cuestiones relacionadas