2009-12-26 24 views
9

En los viejos tiempos, la programación solía implicar menos conjeturas. Escribiría algunas líneas de código y estaré 100% seguro sobre lo que hace el código y lo que no lo hace de un vistazo. Los errores fueron principalmente errores tipográficos, pero no sobre la funcionalidad.¿Qué opina del omnipresente "Test, Test, Test!" ¿principio?

Los últimos años creo que hay una tendencia para esta programación de "prueba y error": escribir el código (como en borrador) y luego depurar iterativamente hasta que el comportamiento del programa parezca cumplir con los requisitos. Pruebe y vuelva a probar, y luego nuevamente. Lo curioso es que, en mi Visual Studio, el botón "Ejecutar" ha sido reemplazado por un botón etiquetado como "Depurar" (= ¡Sé que tienes algunos errores!). Tengo que admitir que en varias aplicaciones que escribo no puedo garantizar un código libre de errores.

¿Qué opinas? O tal vez nuestros sistemas ahora son demasiado complicados (compatibilidades navegador/OS/Service Pack, etc.) y esto justifica las pruebas en todos los tipos de entornos.

+5

Aunque muchas personas se dejan llevar por las pruebas unitarias, no se puede garantizar un código libre de errores en ninguna situación. Si crees que puedes, entonces estás delirante. –

+1

"Escribiría algunas líneas de código y estaré 100% seguro sobre lo que hace el código y lo que no lo hace de un vistazo". ¡Debes haber escrito algunos programas muy simples entonces! – PurplePilot

+3

Creo que esto debería ser una wiki. –

Respuesta

4

La respuesta de una palabra es "Complejidad". ¡La respuesta real es "Complejidad Innecesaria"! Los principios de contabilidad no han cambiado en los últimos 30 años. ¿Por qué entonces escribir un sistema de contabilidad es mucho más difícil hoy en día? Es bueno tener una interfaz gráfica de usuario, pero ¿tenemos que ir por la borda?

El desarrollo de software se ha visto atrapado en un círculo vicioso durante muchos años. La complejidad se está alimentando y, en lugar de reducirla, simplemente la escondemos debajo de capas y capas de envoltorios. Eventualmente algo va a dar.

Cuando favorecemos la forma sobre la función, tenemos que pagar el precio.

+0

¿Qué? Ningún paquete de contabilidad está completo sin al menos actualizaciones trimestrales para incorporar nuevas leyes y reglas. Además, proporcionan mucha más funcionalidad que en 1980. – peterchen

+0

+1 aunque es solo la mitad de la verdad. –

9

He experimentado lo contrario, en realidad. Mientras que solía ser un caso de ejecución hasta que funcionó, ahora hago una prueba unitaria hasta que pasan las pruebas ... y esta parece ser al menos una transición común de razonablemente, hasta donde puedo ver.

Tengo que decir que el código que funcionó la primera vez con solo errores tipográficos tiene nunca sido la norma en mi experiencia. La diferencia es que ahora puedo encontrar los problemas mucho más rápido, y detectar si vuelven viejos problemas. A veces puedo administrar fragmentos de código bastante cortos y simples sin errores (y publicarlos en Stack Overflow ha mejorado esa capacidad) pero ¿sistemas grandes y complejos? Diablos no.

Para responder al título de su publicación, el principio de "prueba, prueba, prueba" es bueno, en mi opinión ... pero no lo asocie con ejecutar todo el programa repetidamente. Lo asocio con pruebas de unidad de funcionamiento con frecuencia. Rara vez necesito usar el depurador para las pruebas unitarias; por lo general, una falla hace que la causa sea adecuadamente obvia por inspección, ya que solo se está probando una pequeña cantidad de código.

+1

La prueba de unidad de prueba y error está bien, es cuando se desarrolla una aplicación o sistema completo mediante métodos de prueba y error con los que se tropieza con problemas. Cuando implementa una única clase o método, la superficie de prueba suele ser relativamente pequeña y, afortunadamente, no implica muchas interacciones o dependencias con otros fragmentos de código. Lo mismo no es cierto de un sistema completo: aquí es donde una buena planificación, diseño y revisión de códigos hacen una gran diferencia. En mi humilde opinión. – LBushkin

4

¿Podría ser que en años posteriores los desarrolladores se hayan dado cuenta de que la "certeza 100%" podría no ser correcta en realidad? El desarrollo de software es muy complejo, y aunque las herramientas han evolucionado a lo largo de los años, también nos hemos dado cuenta de que escribir un buen código es difícil. Es cierto que la depuración y las pruebas unitarias automatizadas nos han hecho más productivos, pero aún producimos errores, tal como lo hicimos en ese momento, solo que ahora tenemos diferentes herramientas para atraparlos.

4

Puede escribir un código que crea que sabe al 100% lo que hace y lo que no, pero siempre existe ese borde en el que no ha pensado o una extraña excepción arrojada que no espera. Algunas veces, la programación de prueba y error puede ser una herramienta útil para reducir un problema, con la ayuda de los depuradores.

Es importante saber qué herramientas están disponibles para ayudar a producir código con errores mínimos.

4

He encontrado que el enfoque Test-Test me ayuda a diseñar el código. A veces, el trabajo que se tiene que hacer es demasiado complejo para hacerlo todo en uno. Las pruebas me obligan a dividirlo en partes más pequeñas y, al resolverlas, puedo unirlas en un todo más grande.

+0

+1. Para mí, las pruebas unitarias son una manera fantástica de pensar en tu código con más detalles, y realmente analizar lo que realmente quieres hacer antes de escribirlo. – Henric

+0

+1 Desarrollo basado en pruebas no es una técnica de prueba, es una técnica de diseño –

4

creo que la ventaja proviene de una forma indirecta: Cuando aceptan pruebas y pruebas de unidad, usted tiene que escribir su aplicación de tal manera que en realidad se puede escribir pruebas:

  • Las clases tienen que ser escrito de tal manera que puede instanciar un solo objeto sin la aplicación completa y el sistema operativo a su alrededor, sino solo unos pocos objetos auxiliares. Esto significa que debe minimizar las dependencias y hacer explícita toda comunicación con el sistema circundante.

  • La implementación de los casos de prueba significa que debe encontrar una secuencia mínima de comandos y llamadas que haga que su clase haga algo significativo. Esto a menudo señala decisiones de diseño incómodas, o le muestra que las clases son muy difíciles de usar para ciertos propósitos.

Con todo, cuando usted abraza pruebas, se termina con un sistema que tiene un mínimo de interdependencias entre sus componentes, y los casos de prueba sirven como documentación de cómo utilizar sus componentes.

3

Las pruebas (ejecución de su sistema) le dicen algo acerca de "la presencia de errores pero NO sobre la ausencia de ellos" (afaik este término es acuñado por dijkstra). Señala la dirección en que la fuerza de su conjunto de pruebas es la clave de las pruebas: "Tiene tantos casos de prueba, que puede decir que muchos errores no existen. Esto implica que grandes partes de su software funcionan como se esperaba ".

Algunos ejemplos para tener una fuerte/poderosa prueba de la suite:

  • Una gran cantidad de código es ejecutado por las pruebas unitarias (el tradicional plazo de cobertura)
  • No tiene pruebas de falsos negativos (prueba que muestran verde, pero de hecho deben ser rojos). Las pruebas falsas negativas son malas, porque te dan un sentido equivocado de la calidad del caso de prueba. Para obtener detalles sobre los buenos test-asertos y falsos-negativos, ver también blog-entry#1 y blog-entry#2.
  • Los requisitos se entienden bien (he visto muchos casos en los que una prueba automatizada estaba probando lo incorrecto y el desarrollador no entendía el requisito de la empresa). Para el desarrollador era verde, pero para los negocios el sistema no funcionaba como se esperaba (otro tipo de ejemplo falso negativo pero en un nivel superior).

En cierto sentido, la corrección de un programa solo se prueba cuando se realiza con pruebas matemáticas (que solo se paga con sistemas de gran importancia vital y dinero). Aún así, puede lograr mucho con las pruebas automatizadas (aparte de las pruebas unitarias, las pruebas de integración automática siempre ayudaron mucho).

En cuanto a la depuración: Utilizo depuración tantas veces como solía hacerlo, pero a veces cuando agrego nuevas funcionalidades al código (mi nuevo caso de prueba muestra verde) rompo otros casos de prueba. Al afirmar al instante, veo que algo salió mal, pero aún no encontré el error. Para localizar la depuración de errores sigue siendo útil (con el caso de prueba rojo ejecuto las rutas de código problemáticas, con el depurador localizo el error).

Si está interesado en la automatización de pruebas eche un vistazo a la obra maestra xUnit Test patterns.

+0

Al escribir pruebas, en lugar de concentrarse en el código, "el desarrollador malinterpretó el requisito del negocio" es menos parecido a suceder. –

0

Actualmente practico Test Driven Development (TDD), o al menos escribo muchas pruebas de unidad para verificar que la mayoría de mi código o todo se comporte de la manera que espero que se comporte. Tomar este enfoque me obliga a mirar mi programa desde la perspectiva del consumidor. Además, a medida que escribo las pruebas, a menudo pienso en límites límite, escenarios adicionales que no imaginé originalmente, etc.

Ahora llegué al punto en que me da miedo realizar cambios en programas anteriores, como temo que romperé algo. Las pruebas de regresión son onerosas, en comparación con la ejecución de un conjunto de pruebas unitarias.

1

He leído un libro ("TDD por ejemplo" de Kent Beck) que de hecho parece llevar ese enfoque de "prueba y error" a un extremo: pero es más como "hacer que las pruebas de la unidad funcionen". Aún así, no pude terminar este libro, una ocurrencia rara, especialmente porque realmente esperaba obtener una mejor comprensión. Sin embargo, cometer código obviamente imbécil para mejorar más tarde me hace estremecer.

Ciencia: Las pruebas automáticas tienen sus ventajas. Sin embargo, no son la bala de plata que se dice que son. Ningún método de prueba es suficiente para determinar los defectos, y otros métodos tienen una mejor tasa de detección.

Gut feel: Nuestros problemas son cada vez más complejos. La complejidad está altamente correlacionada con la cantidad de código que tenemos que administrar. En esta luz, TDD intenta resolver los problemas de con mucho código escribiendo aún más código.

Ventajas: Ahora tenemos un formalismo establecido para que las pruebas sean repetibles, responsables e inmediatamente documentadas. Definitivamente es una forma de salir del "trabajo en mi máquina" y "extraño, funcionó ayer, te daré la última DLL".