2008-10-29 17 views
20

Sé que uno de los principios definitorios del desarrollo impulsado por pruebas es que usted escribe primero las pruebas de su Unidad y luego escribe el código para pasar las pruebas unitarias, pero ¿es necesario hacerlo de esta manera?¿Las pruebas unitarias deben escribirse antes de escribir el código?

Descubrí que a menudo no sé lo que estoy probando hasta que lo escribo, principalmente porque los últimos dos proyectos en los que he trabajado han evolucionado a partir de una prueba de concepto en lugar de ser diseñados .

He intentado escribir mis pruebas unitarias antes y puede ser útil, pero no me parece natural.

+1

Por favor, hagan esta wiki comunitaria, ya que es más que una encuesta que una pregunta real. –

+0

Esto debería ser una pregunta real, en lugar de otra encuesta más. Preferiría que Omar volviera a redactar la pregunta ligeramente para hacerla una pregunta adecuada, en lugar de una pregunta tipo encuesta. –

+0

Estoy feliz de volver a redactar, aunque no estoy seguro de qué volver a pronunciar. –

Respuesta

34

Algunos buenos comentarios aquí, pero creo que una cosa es ser ignorado.

pruebas de escritura primero impulsa su diseño. Este es un paso importante. Si escribe las pruebas "al mismo tiempo" o "poco después" es posible que se pierda algunos beneficios de diseño de hacer TDD en micro pasos.

Se siente muy cursi en un primer momento, pero es increíble ver las cosas se despliegan ante sus ojos en un diseño que no pensó originalmente. Lo he visto suceder

TDD es difícil, y no es para todos. Pero si ya acepta las pruebas unitarias, pruébelo durante un mes y vea qué le hace a su diseño y productividad.

que pase menos tiempo en el depurador y más tiempo pensando en el diseño de afuera hacia adentro. Esas son dos ventajas gigantescas en mi libro.

+0

¿Cómo se crea primero la Prueba Unitaria? ¡El IDE emitirá muchas advertencias y errores y la intellisencia no funcionará! No veo cómo hacerlo. – Pokus

+0

Deje que el IDE genere el código auxiliar del método. Toda la prueba fallará al principio. – flukus

+0

@Pokus: la respuesta rápida es ... Apago la finalización del resumen automático para que intellisense no se interponga en mi camino. CTRL + espacio siempre lo mostrará si lo necesito. Recomiendo mucho ReSharper (http://jetbrains.com/resharper). Ayuda mucho mi flujo de trabajo TDD. –

2

No siempre, pero creo que realmente ayuda cuando lo hago.

2

Tiendo a escribirlos mientras escribo mi código. Como máximo, escribiré las pruebas para saber si la clase/módulo existe antes de escribirlo.

No planifico lo suficiente con tanto detalle para escribir una prueba antes que el código que va a probar.

No sé si esto es un error en mi forma de pensar o método o simplemente TIMTOWTDI.

+0

TIMTOWTD? ¿que demonios es eso? –

+1

Hay más de una forma de hacerlo. Las pruebas de código + más o menos al mismo tiempo todavía se pueden probar. Abre el código, escribe buenas pruebas, termina el código. –

0

No escribo primero las pruebas de unidad reales, pero sí hago una matriz de prueba antes de comenzar a codificar, enumerando todos los escenarios posibles que tendrán que probarse. También hago una lista de casos que tendrán que probarse cuando se realiza un cambio en cualquier parte del programa como parte de una prueba de regresión que cubrirá la mayoría de los escenarios básicos en la aplicación, además de probar completamente el bit de código que cambiado

7

Ha habido studies que muestran que las pruebas unitarias escritas después de que se ha escrito el código son mejores pruebas. La advertencia es que la gente no tiende a escribirlos después del evento. Entonces TDD es un buen compromiso ya que al menos las pruebas se escriben.

Así que si escribe pruebas después de haber escrito el código, es bueno para usted, le sugiero que se quede.

Tiendo a encontrar que hago una mezcla. Cuanto más entiendo los requisitos, más pruebas puedo escribir desde el principio. Cuando los requisitos, o mi comprensión del problema, son débiles, tiendo a escribir pruebas después.

+0

¿Podrían proporcionar enlaces a los estudios? Gracias – roundcrisis

+1

El enlace en esta respuesta apunta a una publicación de blog que cuestiona los resultados del estudio, no a estudios reales con diferentes resultados. Debo descartar la validez de la primera línea de esta respuesta como resultado. –

+1

El enlace apunta a un análisis detallado de las conclusiones que el equipo del estudio extrajo y las razones por las cuales sus conclusiones fueron incorrectas. El estudio realmente mostró claramente que la prueba después es mejor que la prueba anterior (siempre que se lleve a cabo) –

2

Empiezo por cómo me gustaría llamar a mi "unidad" y hacerla compilar. como:

picker = Pick.new 
item=picker.pick('a') 
assert item 

entonces creo

class Pick 
def pick(something) 
return nil 
end 
end 

luego seguir usando la selección en mi caso "prueba" para que pudiera ver cómo me gustaría que sea llamado y cómo iba a tratar diferentes tipos de comportamiento Cada vez que me doy cuenta de que podría tener problemas en algunos límites o algún tipo de error/excepción, intento disparar y obtener un nuevo caso de prueba.

Así que, en resumen. Sí. La relación haciendo la prueba anterior es mucho más alta que no hacerlo.

0

Recuerda con la programación Extreme tus pruebas son tu documentación. Entonces, si no sabe lo que está probando, ¿no sabe lo que quiere que su aplicación vaya a hacer?

Usted puede comenzar con "historias" que podrían ser algo así como

"Los usuarios pueden obtener la lista de preguntas"

Luego, a medida que comience a escribir código para resolver las pruebas unitarias. Para resolver lo anterior, necesitará al menos una clase de usuario y pregunta. Así que a continuación, puede empezar a pensar en los campos:

"clase de usuario tiene el nombre fecha de nacimiento Dirección Telf campos Locked"

etc. espero que ayude.

Crafty

0

Sí, si está utilizando verdaderos principios TDD. De lo contrario, siempre y cuando estés escribiendo las pruebas unitarias, lo estás haciendo mejor que la mayoría.

En mi experiencia, por lo general es más fácil escribir las pruebas antes del código, ya que al hacerlo de esa manera usted se da una herramienta de depuración fácil de usar como se escribe el código.

0

Los escribo al mismo tiempo. Creo el código de esqueleto para la nueva clase y la clase de prueba, y luego escribo una prueba de alguna funcionalidad (que luego me ayuda a ver cómo quiero que se llame al nuevo objeto) y la implemento en el código.

Por lo general, no lo termino con código elegante en la primera ronda, la cual es normalmente bastante hacky. Pero una vez que todas las pruebas estén funcionando, puedes refactorizar hasta que termines con algo bastante limpio, ordenado y que pueda ser sólido como una roca.

2

Creo que escribir la prueba primero ayuda a definir lo que el código realmente debería hacer. Demasiadas veces las personas no tienen una buena definición de lo que se supone que debe hacer el código o cómo debería funcionar. Simplemente comienzan a escribir y inventar a medida que avanzan. La creación de la prueba primero te hace enfocarte en lo que hará el código.

1

Escribir las pruebas primero define cómo se verá su código, es decir, tiende a hacer que su código sea más modular y comprobable, por lo que no crea un método de "inflado" con una funcionalidad muy compleja y superpuesta. Esto también ayuda a aislar todas las funciones básicas en métodos separados para una prueba más sencilla.

6

TDD no se trata de las pruebas, pero ¿cómo las pruebas de unidades de su código. Así que, básicamente, estás escribiendo pruebas para permitir que una arquitectura evolucione de forma natural (¡y no olvides refactorizar! De lo contrario, no obtendrás muchos beneficios de ella). Que tenga un arsenal de pruebas de regresión y documentación ejecutable después es un buen efecto secundario, pero no la razón principal detrás de TDD.

Así que mi voto es: Prueba primera

PD: Y no, eso no quiere decir que usted no tiene que planificar su arquitectura antes, pero que podría reconsiderar si las pruebas que dicen que ¡hazlo!

2

Las directivas son sugerencias sobre cómo podría hacer cosas para mejorar la calidad general o la productividad o incluso ambos productos finales. De ninguna manera son leyes para ser obedecidas, menos te aprietas en un instante por el dios de la práctica de codificación adecuada.

Aquí está mi compromiso con la toma y la encontré bastante útil y productiva.

Por lo general, la parte más difícil de corregir son los requisitos y justo detrás de la usabilidad de su clase, API, paquete ... Entonces es la implementación real.

  1. Escribir interfaces (que va a cambiar, pero pasará un largo camino para saber QUÉ se tiene que hacer)
  2. Escribir un programa sencillo de utilizar las interfaces (estúpidos principal). Esto ayuda en gran medida a determinar CÓMO se va a usar (regrese a 1 tan a menudo como sea necesario)
  3. Escribir pruebas en la interfaz (El bit que integé desde TDD, otra vez vuelva a 1 tan a menudo según sea necesario)
  4. escribir el código real detrás de las interfaces
  5. pruebas de escritura en las clases y la implementación real, utilice una herramienta de cobertura para asegurarse de que no se olvide de las rutas de ejecución Weid

lo tanto, sí me escribir pruebas antes de la codificación, pero nunca antes me di cuenta de lo que hay que hacer con un cierto nivel de detalles. Estas suelen ser pruebas de alto nivel y solo tratan el conjunto como una caja negra. Normalmente permanecerá como pruebas de integración y no cambiará mucho una vez que las interfaces se hayan estabilizado.

Luego escribo un montón de pruebas (pruebas unitarias) sobre la implementación detrás de esto, estas serán mucho más detalladas y cambiarán a menudo a medida que la implementación evolucione, a medida que se optimice y se amplíe.

¿Es esto estrictamente hablando TDD? Extremo? Ágil...? lo que sea... ? No lo sé, y francamente no me importa. Funciona para me. Lo ajusto según las necesidades y conforme avanza mi comprensión de la práctica del desarrollo de software.

mi 2 céntimos

5

tengo los equipos de desarrollo de plomo durante los últimos 6-7 años. Lo que sí puedo decir con certeza es que, como desarrollador y desarrolladores con los que he trabajado, la diferencia en la calidad del código es enorme si sabemos dónde encaja nuestro código en el panorama general.

Test Driven Development (TDD) nos ayuda a responder "¿Qué?" antes de responder "¿Cómo?" y hace una gran diferencia.

Entiendo por qué puede haber temores sobre no seguirlo en el tipo de PoC de desarrollo/trabajo de arquitecto. Y tiene razón, puede que no tenga todo el sentido seguir este proceso.Al mismo tiempo, me gustaría enfatizar que TDD es un proceso que cae en la Fase de Desarrollo (sé que suena obsoleto, pero entiendes el punto :) cuando las especificaciones de bajo nivel son claras.

1

Personalmente, creo que las pruebas unitarias pierden mucha efectividad si no se hacen antes de escribir el código.

El viejo problema con las pruebas es que no importa cuánto lo pensemos, nunca se nos ocurrirán todos los escenarios posibles para escribir una prueba para cubrir.

Obviamente, las pruebas unitarias no lo impiden por completo, ya que son pruebas restrictivas, ya que solo se observan una unidad de código que no cubre las interacciones entre este código y todo lo demás, pero proporciona una buena base para escribir código limpio en el primer lugar que debería al menos restringir las posibilidades de problemas de interacción entre módulos. Siempre he trabajado según el principio de mantener el código tan simple como sea posible; de ​​hecho, creo que este es uno de los principios clave de TDD.

Así que comenzando con una prueba que básicamente dice que puede crear una clase de este tipo y construirla, en teoría, escribir una prueba para cada línea de código o al menos cubrir cada ruta a través de una pieza de código en particular. Diseñando sobre la marcha Obviamente, se basa en un diseño inicial bruto producido inicialmente, para darle un marco para trabajar.

Como dices es muy antinatural para empezar y puede parecer una pérdida de tiempo, pero me he visto de primera mano que vale la pena a la larga cuando aparecen los defectos y muestra los módulos que estaban completamente escritos usando TDD tienen defectos mucho más bajos en el tiempo que otros.

2

He estado programando durante 20 años, y prácticamente nunca he escrito una línea de código en la que no haya realizado algún tipo de prueba de unidad. Honestamente, sé que la gente lo hace todo el tiempo, pero cómo alguien puede enviar una línea de código que no ha tenido algún tipo de ejecución de prueba que está más allá de mí.

A menudo, si no existe un marco de prueba en su lugar, simplemente escribo un main() en cada clase que escribo. Agrega un pequeño fragmento a su aplicación, pero alguien siempre puede eliminarlo (o comentarlo) si lo desean, supongo. Realmente me gustaría que hubiera solo un método de prueba() en tu clase que compilara automáticamente las compilaciones de lanzamiento. Me encanta que mi método de prueba esté en el mismo archivo que mi código ...

Así que hice ambas cosas Desarrollo impulsado por prueba y desarrollo probado. Puedo decirte que TDD realmente puede ayudar cuando eres un programador principiante. Le ayuda a aprender a ver su código "desde afuera", que es una de las lecciones más importantes que un programador puede aprender.

TDD también lo ayuda a ponerse en marcha cuando está atascado. Puedes escribir una pieza muy pequeña que sabes que tu código tiene que hacer, luego ejecutarla y arreglarla, se vuelve adictivo.

Por otro lado, cuando está agregando código existente y sabe exactamente lo que quiere, es un lanzamiento. Su "Otro código" a menudo prueba su nuevo código en su lugar. Aún debe asegurarse de probar cada ruta, pero obtiene una buena cobertura simplemente ejecutando las pruebas desde el front-end (excepto en los idiomas dinámicos; para aquellos que realmente deberían tener pruebas unitarias para todo lo que sea).

Por cierto, cuando estaba en un proyecto bastante grande de Ruby/Rails teníamos un porcentaje muy elevado de cobertura de prueba. Refactorizamos una clase de modelo principal y central en dos clases. Nos habría llevado dos días, pero con todas las pruebas que tuvimos que refactorizar terminó cerca de dos semanas. Las pruebas NO son completamente gratis.

0

Cuando escribe algo con el que está escribiendo, le ayuda escribir primero todo lo que verificará regularmente y luego escribir esas características.Más veces, entonces esas características no son las más importantes para la pieza de software que está escribiendo. Ahora, en el otro lado, no hay balas de plata y las cosas nunca deben seguirse al pie de la letra. El juicio del desarrollador juega un papel importante en la decisión de usar el desarrollo impulsado por prueba versus el último desarrollo de prueba.

1

Antes, durante y después. Antes es parte de la especificación, el contrato, la definición de la obra Durante es cuando se descubren casos especiales, datos incorrectos, excepciones durante la implementación. Después de mantenimiento, evolución, cambio, nuevos requisitos.

1

No estoy seguro, pero según su descripción, creo que podría haber un malentendido sobre lo que realmente significa "probar primero". Hace no significa que usted escribe todo primero sus pruebas. Lo que significa es que usted tiene un ciclo muy apretado de

  1. escribir una sola prueba, mínimo
  2. hacen que el paso de la prueba escribiendo el código de producción mínima necesaria
  3. escribir la siguiente prueba de que se producirá un error
  4. hacer pasar todas las pruebas existentes cambiando el código de producción existente de la manera más simple posible
  5. refactorizar el código (tanto de prueba como de producción) para que no contenga duplicación y sea expresivo
  6. continuar con 3. hasta que no se le ocurra otra prueba sensata

Un ciclo (3-5) generalmente solo lleva unos minutos. Con esta técnica, realmente evoluciona el diseño mientras escribe las pruebas y el código de producción en paralelo. No hay mucho diseño inicial involucrado en absoluto.

Sobre la cuestión de si es "necesario" - no, obviamente no lo es. Ha habido proyectos innumerables exitosos sin hacer TDD. Pero existe una fuerte evidencia de que el uso de TDD generalmente conduce a una calidad significativamente mayor, a menudo sin impacto negativo en la productividad. ¡Y es divertido también!

Ah, y considerando que no se siente "natural", es solo una cuestión de lo que está acostumbrado. Conozco personas que son bastante adictas a obtener una barra verde (el típico signo xUnit para "pasar todas las pruebas") cada dos minutos.

1

Hay tantas respuestas ahora y todas son diferentes. Esto se asemeja perfectamente a la realidad que existe. Todos lo hacen de manera diferente. Creo que hay un gran malentendido sobre las pruebas unitarias. Me parece que la gente escuchó sobre TDD y dijeron que es bueno. Luego comenzaron a escribir pruebas unitarias sin realmente entender qué es realmente TDD. Acaban de obtener la parte "oh sí, tenemos que escribir pruebas" y están de acuerdo. También escucharon sobre esto "debes escribir tus pruebas primero" pero no toman esto en serio.

Creo que es porque no entienden los beneficios de la prueba primero que a su vez solo se puede entender una vez que lo haya hecho de esta manera durante algún tiempo. Y siempre parecen encontrar 1.000.000 de excusas por las que no les gusta escribir las pruebas primero. Porque es muy difícil cuando descubro cómo encajarán todas las cosas, etc. etc. En mi opinión, todo es excusa para que se escondan de su incapacidad para disciplinarse una vez, probar el enfoque de probar primero y comenzar a ver los beneficios.

Lo más ridículo si comienzan a argumentar "No estoy convencido de esta prueba, pero nunca lo hice así" ...excelente ...

Me pregunto de dónde vienen las pruebas unitarias. Porque si el concepto realmente se origina en TDD, es ridículo cómo la gente se equivoca.

Cuestiones relacionadas