2008-10-03 12 views
33

Al haber descubierto recientemente este método de desarrollo, creo que es una metodología bastante buena. Por lo tanto, para mi primer proyecto, tengo un pequeño DLL de código (en C# .NET, por lo que vale), y quiero hacer un conjunto de pruebas para este código, pero estoy un poco perdido en cuanto a cómo y donde empezar.Desplazar el código existente a Test Driven Development

Estoy usando NUnit, y VS 2008, cualquier consejo sobre el tipo de clases para empezar, para qué escribir las pruebas y cualquier consejo sobre cómo mover el código al desarrollo basado en pruebas sería en gran medida apreciado.

Respuesta

53

Vea el libro Working Effectively with Legacy Code de Michael Feathers.

En resumen, es mucho trabajo refactorizar el código existente en código comprobable y probado; A veces es demasiado trabajo ser práctico. Depende de qué tan grande es la base de código, y de cuánto dependen las diversas clases y funciones entre sí.

Refactorear sin pruebas introducirá cambios en el comportamiento (es decir, errores). Y los puristas dirán que en realidad no se está refaccionando debido a la falta de pruebas para verificar que el comportamiento no cambie.

En lugar de agregar pruebas en toda la plataforma a toda su aplicación a la vez, agregue pruebas cuando trabaje en un área de código. Lo más probable es que tenga que regresar a estos "puntos de acceso" nuevamente.

Agregue pruebas de abajo arriba: pruebe las clases pequeñas e independientes y las funciones para la corrección.

Agregue pruebas de arriba hacia abajo: pruebe los subsistemas enteros como cuadros negros para ver si su comportamiento cambia con los cambios en el código. Y entonces puede pasar a través de ellos para descubrir qué está pasando. Este enfoque probablemente te beneficiará más.

Al principio, no se preocupe demasiado sobre cuál es el comportamiento "correcto" mientras agrega pruebas, busque detectar y evitar cambios en el comportamiento. Los sistemas grandes no probados a menudo tienen comportamientos internos que pueden parecer incorrectos, pero de los que dependen otras partes del sistema.

Considere aislar dependencias como base de datos, sistema de archivos, red, para que puedan intercambiarse entre proveedores de datos falsos durante la prueba.

Si el programa no tiene interfaces internas, líneas que definen el límite entre un subsistema/capa y otro, entonces puede que tenga que intentar introducirlas y probarlas.

Además, marcos de burlas automáticas como Rhinomocks o Moq pueden ayudar a simular las clases existentes aquí. Realmente no he encontrado la necesidad de ellos en el código diseñado para la capacidad de prueba.

+0

Creo que su respuesta es mucho mejor con el texto de resumen: podemos obtener más detalles de los enlaces si queremos, pero podemos entender su posición sin leer. –

4

El código comprobable es fácil de detectar, mediante las pruebas que lo acompañan. Si hay algunos, debe ser comprobable. Si no hay ninguno, asuma lo contrario. ;)

Dicho esto: Test Driven Development (TDD) no es tanto una estrategia de prueba como una estrategia de diseño. Las pruebas que escribe primero ayudan a diseñar la interfaz de sus clases, así como también a obtener el alcance de sus clases (o subsistemas).

Tener las pruebas que ha creado durante TDD y ejecutarlas más tarde hace buenas pruebas, pero es simplemente un (muy bienvenido) efecto secundario de esa filosofía de diseño.

Dicho esto, se espera que no se pruebe la resistencia del código.Escuche su código y cambie la interfaz para poder probarlo fácilmente. Lo más probable es que lo rediseñes cuando comiences a escribir pruebas.

+1

No sé sobre la resistencia a las pruebas, pero he logrado volver a exponer un error que el diseñador de formularios de VS adelantó hace un tiempo que me estaba dando muchos problemas al escribir una prueba para cubre esa posibilidad. ¡Hurra! –

10

Working Effectively with Legacy Code es mi Biblia cuando se trata de migrar código sin pruebas a un entorno probado por la unidad, y también proporciona una gran cantidad de información sobre lo que hace que el código sea fácil de probar y cómo probarlo.

También encontré Test Driven Development by Example y Pragmatic Unit Testing: in C# with NUnit para ser una introducción decente a las pruebas unitarias en ese entorno.

Un método simple para iniciar TDD es comenzar a escribir pruebas primero a partir de hoy y asegurarse de que cada vez que necesite tocar su código existente (no probado), escriba pruebas de aprobación que verifiquen el comportamiento existente del sistema antes de cambiarlo para que pueda volver a ejecutar esas pruebas después para aumentar su confianza en que no ha roto nada.

1

Su DLL proporciona algún tipo de servicio. Para cada servicio, ¿qué debe hacer antes de recibir este servicio? ¿Qué parámetros debe pasar para obtener este servicio? ¿Cómo sabría que el servicio solicitado se ejecutó correctamente?

Una vez que tenga las respuestas a esas preguntas, puede escribir una primera prueba. Tales pruebas se llamarían más bien Characterization tests que las pruebas unitarias, pero probablemente sería más fácil escribir que las pruebas unitarias si el DLL no se desarrolló utilizando TDD.

Las pruebas de caracterización también se discuten en M. Feathers '"Trabajando eficazmente con el código heredado", que se recomienda en otras respuestas.

Además, asegúrese de escribir una prueba de falla antes de agregar cualquier nueva línea de código.

9

Lo llamo "Test Driven Reverse Engineering".

Comience "en la parte inferior": cada clase se puede examinar por separado y se puede escribir una prueba para ella. En caso de duda, adivina.

Cuando está haciendo un TDD ordinario en la dirección de avance, trata la prueba como sagrada y supone que probablemente el código está roto. Algunas veces la prueba es incorrecta, pero su posición inicial es que es el código.

Cuando está haciendo TDRE, el código es sagrado - hasta que pueda probar que el código tiene un error de larga data. En el caso inverso, usted escribe pruebas alrededor del código, ajusta las pruebas hasta que funcionen y afirma que el código funciona.

Luego, puede profundizar en el código incorrecto. Algunos malos cade tendrán casos de prueba sensibles, esto solo necesita ser limpiado. Sin embargo, algunos códigos incorrectos también tendrán un caso de prueba sin sentido. Esto puede ser un error o un diseño torpe que puede rectificar.

Para juzgar si el código es realmente incorrecto, también debe comenzar en la parte superior con casos de prueba generales. Los datos en vivo que realmente funcionan son un comienzo. Además, los datos en vivo que producen cualquiera de los errores conocidos, también son un buen lugar para comenzar.

He escrito pequeños generadores de código para convertir datos en vivo en casos de prueba unitaria. De esa manera, tengo una base consistente para probar y refactorizar.

Cuestiones relacionadas