archivo

Archivo de la etiqueta: TDD

Hay muchos desarrolladores que aplican TDD en sus desarrollos o, al menos, desarrollan pruebas unitarias para el software que están implementando.

Sobre ambos aspectos TDD (las pruebas unitarias se construyen antes) o las pruebas unitarias en general hay defensores y detractores y como suele suceder en tantos aspectos, no hay una verdad absoluta, sino que la aplicación o no de estas estrategias dependen del contexto en que se realiza el desarrollo, del tipo de sistema y del equipo de programadores.

Pese a que hablo de contexto incluso en situaciones favorables existen reticencias por muchos desarrolladores que lo consideran una pérdida de tiempo o una carga que llevar encima desde que se implementan, sin embargo quienes lo utilizan y lo consideran como una actividad más dentro de la programación lo suelen aplicar prácticamente en cualquier contexto.

No voy a defender a unos o a otros, cada cual tiene su criterio. Desde mi punto de vista la posibilidad de realizar testing unitario y su automatización supuso en su día una revolución en el desarrollo de software y en el mantenimiento de sistemas porque todo lo que sea establecer controles que permitan construir sistemas más robustos y entregar productos con menos errores debería ser bienvenido

Martin Fowler como buen defensor de estas prácticas realizó la siguiente reflexión sobre los frameworks de pruebas unitarias: “Nunca en el campo de desarrollo de software tantos le debieron tanto a tan pocas líneas de código”.

Solo en circunstancias ideales un proyecto de desarrollo de software no está sometido a incertidumbre. Y en muy contadas ocasiones, en proyectos de pequeño tamaño y/o con procesos muy estables se puede producir algo parecido a esas circunstancias ideales.

Por eso las técnicas de estimación tienen un grave problema para determinar el coste final del software, si bien es importante realizar la mejor estimación posible con el conocimiento disponible ya que un proyecto debe contar con un presupuesto, independientemente de que posteriormente se pueda ampliar o no (si hay circunstancias que lo justifican).

Pero, ¿tantas variables del proyecto pueden cambiar a lo largo del proceso de desarrollo?.

Scott L. Bain es un desarrollador, consultor, conferenciante y autor especializado en metodologías ágiles y TDD que cuenta con más de treinta y cinco años de experiencia en este negocio y responde de manera adecuada a esa cuestión en su siguiente reflexión: “La inutilidad de la lucha contra el cambio: Requisitos, tecnologías, equipos, las prioridades, las empresas, el uso, los usuarios, todo cambiará. Hay cosas que no se pueden saber hasta que se nos presentan. Date por vencido. El cambio es inevitable. Nuestro proceso debe ser un proceso, por lo tanto, de cambio.”

Bogdan Bereza-Jarocinski es un desarrollador de software y psicólogo polaco especializado en la calidad del software, más concretamente en el campo del testing. No obstante, ha pasado prácticamente por los diferentes perfiles clásicos por los que suele pasar un desarrollador: programador, analista, jefe de proyectos…

Me ha resultado interesante una reflexión que realizó en el año 2000, sobre el proceso de automatización del testing (traducción libre): “Introducirse en la automatización de las pruebas es, a veces, como un romance: tormentoso, emocional, en ocasiones un fracaso y en otras un éxito espectacular”.

Esta cita puede ser válida en muchos campos del desarrollo de software cuando existe un cambio de la manera en que tradicionalmente se han hecho las cosas a otra diferente: nunca es fácil, genera un cierto desgaste, siempre aprendes y el resultado puede ser bueno o nefasto.

La automatización del testing, en todos los niveles, no solo a nivel de la definición de pruebas unitarias o la aplicación de técnicas orientadas a las mismas como TDD, supone un cambio de mentalidad importante en el desarrollo de software, ya que es la consecuencia de entender, por fin, que:

– El software es de naturaleza adaptativa o evolutiva, donde los mismos usuarios van refinando con el uso del producto la idea que tenían inicialmente del mismo y donde los mismos procesos de negocio evolucionan, dando lugar a nuevas versiones de la aplicación.

– Donde la calidad del software es un objetivo esencial a conseguir por cualquier desarrollador y que parte de esa calidad final depende de la capacidad de localizar errores en las etapas más tempranas posibles (para reducir los costes asociados a su corrección) y para reducir el número y criticidad de los mismos que llegan a entornos de producción.

Detectar errores al final puede ser demasiado tarde. Si las fallas son funcionales, la arquitectura no es buena, la codificación deja mucho que desear y la culpa es tuya (en muchos casos aunque no lo sea, si el cliente tiene fuerza y no te respeta) el esfuerzo de corregirlo será tan importante que los beneficios del proyectos, si los hay, se diluirán y si hay pérdidas se multiplicarán.

El testing debe acompañar al proyecto desde que se concibe. Los que nos dedicamos a esto tenemos el defecto de que damos demasiadas cosas por supuesto y nos pasan demasiadas cosas por eso. Desde el plan de proyecto, desde el primer acta de reunión, todo debe ser revisado, todo debe ser validado.

¿Es eso ágil? Habrá quien piense que no, pero desde mi punto de vista no hay nada más ágil que no tener que volver a hacer algo de nuevo sin que el usuario te haya dicho que lo cambies. ¿Qué hay que hacer quince veces una pantalla? Pues se hace, si con ello y en cada paso estamos más cerca de que el usuario vea satisfechas sus expectativas. Evidentemente eso cuesta dinero y si no hay presupuesto detrás, el usuario deberá intentar ser más preciso (o renunciar a funcionalidades menos prioritarias).

En el proceso de codificación las pruebas deben hacerse cuanto antes. Si consideras que TDD es demasiado, aplica pruebas unitarias una vez desarrollado el código, si también consideras que eso es demasiado aplica la técnica que prefieras, pero por favor, prueba lo que estés haciendo y no des por supuesto que determinadas partes del código funcionan salvo que estés muy seguro.

¿Cuánto tiempo dedica tu equipo de proyecto a realizar testing?, ¿cuál es la proporción respecto al esfuerzo dedicado netamente a desarrollar?, ¿se utilizan estrategias que automaticen determinados tipos de test como por ejemplo las pruebas unitarias?, ¿vas más allá y aplicas TDD?, ¿usas integración continua?, ¿en qué etapas realizas pruebas?, ¿comienzan desde el mismo proceso de análisis?, ¿cuál es la participación del usuario (o el cliente en general) en las mismas?, ¿en qué proporción es explotaratoria y en qué proporción se basa estrictamente en casos de prueba?, ¿participan personas distintas al equipo de proyecto en pruebas de tipo funcional?, ¿se realiza testing de seguridad, usabilidad, rendimiento?, dicho testing, ¿cuánto es manual y cuánto está asistido por herramientas?, ¿no se realizan pruebas de la aplicación en un entorno de integración del cliente?, ¿realizas análisis estático de código?, en dicho análisis, ¿tienes definidos unos umbrales mínimos de calidad exigibles a las distintas métricas?, cuando vas a entregar una nueva versión de un producto software, ¿haces pruebas de regresión?.

Aunque tal vez todo lo anterior se pueda resumir en par de preguntas, ¿qué nivel de importancia le das al testing en las aplicaciones que desarrollas?, ¿tienes mecanismos para comprobar si se realiza testing y para evaluar la efectividad del mismo?.

El testing se infravalora de manera muy injusta. Bien realizado ahorra muchos problemas y por encima de eso, permite conservar tu imagen y tu dinero.

Hay muchos que piensan que el testing no es ágil y yo respeto las opiniones de cada uno, independientemente de que las comparta o no. Como he dicho muchas veces, lo que no es ágil es tener que repetir trabajo no por evolucionar una funcionalidad o un componente software, sino para corregir errores que perfectamente detectables en etapas anteriores.

Es más ágil (y menos arriesgado) prevenir un incendio que intentar sofocarlo después.

Boris Beizer es un autor e ingeniero de software americano (aunque nacido en Bélgica) especializado en el campo de la calidad del software y del testing. Sus primeras publicaciones datan de finales de la década de los cincuenta, aunque su etapa más prolífica fue en las décadas de los setenta y de los ochenta.

El testing es un campo dentro de la ingeniería del software un tanto controvertido. La mayoría de los profesionales consideramos necesarias las pruebas en el proyecto de desarrollo de software, si bien no hay coincidencia en cuanto a la intensidad, los momentos y la metodología.

Soy de la opinión de que no todos los proyectos y sistemas de información deben tener un mismo tratamiento y que independientemente de que exista una cierta metodología en las pruebas, estas deben girar alrededor del testing ágil y del exploratorio.

También soy partidario de que las clases con mayor acoplamiento sean cubiertas mediante pruebas unitarias (no necesariamente desarrollando según técnicas de desarrollo guiadas por las pruebas (TDD)) y que se deben minimizar los efectos colaterales a través de las pruebas de regresión.

En cuanto a los momentos, el testing debe aplicarse desde las etapas más tempranas del software, si bien los actores pueden ser distintos a las pruebas realizadas sobre el producto.

Y como estrategia, la utilización de integración continua permite detectar problemas de carácter unitario y de integración lo antes posible y a reducir los problemas en la fase de implantación.

Boris Beizer realiza la siguiente reflexión (traducción libre): “Una amenaza bien vale mil pruebas”.

Desgraciadamente nos acordamos de un proceso de testing bien realizado cuando ya los errores han salido a la luz y lo peor de eso, cuando su corrección requiere de un esfuerzo considerable, cuando ha impactado gravemente en el negocio o cuando nos crea un problema.

Cuando mayor sea la criticidad del sistema más peso debe tener el proceso de testing y más peso debe cobrar la metodología y sistematización.

En el artículo anterior vimos las actividades que definían al proceso de implantación y de las consecuencias de que el tiempo necesario para realizar esa actividad superasen unos umbrales admisibles para el proyecto de desarrollo de software en cuestión.

La aplicación de una metodología o enfoque ágil o la utilización, en general, de alternativas iterativas e incrementales suponen por su propia naturaleza una disminución de los tiempos de implantación, sobre todo, una vez que ya se han realizado varias evoluciones del sistema.

Sin embargo, si el tiempo necesario para realizar las implantaciones resulta superior al tiempo de iteración definido tenemos un problema ya que provoca una acumulación de las entregas y que buena parte del tiempo invertido en el proceso de implantación se pierda. Esta situación no debería mantenerse mucho tiempo y para solucionarla sería necesario retrasar una entrega hasta que se pueda subir una acumulación de evoluciones a producción.

Estas situaciones pueden producirse en más ocasiones de las que podemos pensar, ya que lo mismo los trabajos siguiendo metodologías ágiles, parten de una versión del producto avanzada y que no ha sido implantada todavía (o no se han implantado con éxito), los equipos encargados de testing y de paso a producción tienen una carga de trabajo elevada, otras prioridades, etc…

Soy de la opinión de que para poder trabajar de manera adecuada hay que estabilizar la situación, es decir, si la implantación de un producto resulta compleja o está dando problemas, hay que centrar los esfuerzos en ella y adaptar los desarrollos que se están haciendo a esa circunstancia.

Además de la aplicación de enfoques ágiles, ayuda mucho la existencia de unos entornos de integración y de preproducción los más parecidos posibles a los de reales, la aplicación de la integración continua, la utilización de técnicas de desarrollo guiadas por las pruebas (TDD) o al menos la aplicación de una estrategia adecuada de aplicación de pruebas unitarias, para reducir de esta forma la aparición de efectos colaterales y disminuir los tiempos necesarios para las pruebas de regresión y la corrección de este tipo de incidencias.

Además de lo anterior es importante que con carácter previo a la entrega el producto haya sido probado de manera adecuada por el equipo de proyecto (nada de entregas a ciegas o de pruebas superficiales).

También resulta muy adecuado el establecimiento de itinerarios de testing (todas las aplicaciones no requieren el mismo nivel de testing, ni todas las circunstancias son similares), la aplicación de testing ágil, proporcionar a los proveedores información detallada sobre las características de nuestro entorno de producción, la aplicación de una política de prioridades a los equipos encargados del paso a producción acorde a la problemática existente en cada momento, etc…