martes, 23 de febrero de 2010

Volviendo a los clásicos I

- El Arte de Probar el Software - Glenford J. Myers – 1983 – Editorial El Ateneo

Ya que se está hablando en estos días de las pruebas que se hicieron para el cambio a año 2000, y que mucho se ha avanzado desde esa época en lo relativo a pruebas de software, vale la pena volver a leer a los referentes, y validar cómo siguen vigentes la mayoría de sus conceptos.

En esta línea, hemos releído a Myers, y queremos compartir un extracto de los puntos que nos parecen más interesantes (y siempre vigentes).

Qué mejor inicio del libro que con un ejercicio muy corto, para realizar una autoevaluación, donde se pide que se preparen casos de prueba sobre un programa muy sencillo, con el que se demuestra que aún siendo el problema trivial, la tarea no es fácil.

Ejercicio: El programa lee tres números enteros de una tarjeta, los que son interpretados como representaciones de las longitudes de los lados de un triángulo. El programa escribe un mensaje que informa si el triángulo es escaleno, isósceles o equilátero.

El libro encara un tratamiento más bien práctico que teórico del tema. Para el autor, más importante que los distintos puntos de vistas técnicos, es la adecuada elección de quién deberá hacer la prueba, y la adopción de un modo de pensar correcto. Estas cuestiones parecen contribuir en mayor grado al éxito de una prueba que otras de orden puramente técnico, por eso arranca con estas definiciones para luego ir a otras de naturaleza más técnica.

Punto 1 - Qué es probar

Las definiciones incorrectas sobre el término Probar tiene influencia psicológica en el momento de realizar los casos de pruebas, y son la causa principal de que las pruebas resulten deficientes.

Como ejemplo de tales definiciones se pueden dar las siguientes:

- Probar es demostrar que no hay errores presentes en el programa”

- “el propósito de probar es mostrar que el programa realiza correctamente las funciones esperadas”

- “probar es el proceso que lleva a confiar en que un programa hará lo que se supone que debe hacer”.

Estas definiciones son incorrectas porque describen casi lo opuesto de lo que debemos considerar como prueba de un programa. Dejando de lado las definiciones, pensemos que cuando se prueba un programa, se desea agregarle un valor. Agregar valor significa aumentar su calidad o confiabilidad, lo que, a su vez, significa encontrar y eliminar errores. De aquí que no se deba probar un programa para mostrar que funciona; más bien es conveniente comenzar con la suposición de que el programa contiene errores y luego probar el programa para encontrar tantos errores como sea posible. Una definición más apropiada es:

Prueba es el proceso de ejecutar un programa con el fin de encontrar errores

Puesto que los seres humanos tienden a estar fuertemente orientados hacia la obtención de metas, si nuestra meta es demostrar que el programa no contiene tiene errores, estaremos entonces subconscientemente dirigidos hacia este fin, y tenderemos a seleccionar datos de pruebas con baja probabilidad de hacer que el programa falle. Esta definición implica que la prueba es un proceso destructivo.

Otra manera de reforzar la definición adecuada de prueba es utilizar bien las definiciones de las palabras “exitoso” y “no exitoso”. Un caso de prueba que no encuentre error alguno constituye un desperdicio de tiempo y dinero: éste sería un caso de prueba “no exitoso”, en cambio aquel que sí lo encuentre es un caso “exitoso”.

Punto 2 - Principios fundamentales

Estos principios parecen ser obvios y son importantes, y sin embargo con demasiada frecuencia se los ignora:

· La definición del resultado esperado a la salida del programa es una parte integrante y necesaria de un caso de prueba.

· Un programador debe evitar probar su propio programa.

· Una empresa de programación no debería probar sus propios programas.

· Inspeccionar concienzudamente el resultado de cada prueba.

· Los casos de prueba deben ser escritos tanto para condiciones de entradas inválidas e inesperadas como para condiciones válidas y esperadas.

· Examinar un programa para comprobar que no hace lo que se supone que debe hacer es sólo la mitad del problema. La otra mitad consiste en ver si el programa hace lo que no se supone que debe hacer.

· Evitar los casos de prueba desechables a menos que el programa sea verdaderamente un programa desechable.

· No planear un esfuerzo de prueba con la suposición tácita de que no se encontrarán errores.(uso de definición incorrecta de prueba, suponiendo que la prueba es el proceso de mostrar que el programa funciona correctamente)

· Las pruebas constituyen una tarea altamente creativa y son un desafío intelectual.

Punto 3 - Probar tempranamente

Cuanto antes se encuentren los errores, más bajo será el costo de corregirlos. Por ello se deben realizar inspecciones y recorridas en el código.

Las Inspecciones de Codificación: son procedimientos y técnicas para la revisión de programas en busca de errores, efectuada por un grupo de 4 personas (moderador, programador, diseñador del programa, tester).

Forma de trabajo: El moderador días antes distribuye las listas de programas y las especificaciones de diseño, se divide en dos sesiones la primea se le pide al programador que describa sentencia por sentencia la lógica del programa y se le realizan preguntas. La experiencia demuestra que el programador encuentra más errores que los otros miembros del equipo de inspección. En la segunda sesión se analiza el programa por medio de una lista de ayuda de memoria (checklist) preparada anteriormente que contiene una lista con los errores más frecuentes en programación.

El tiempo de las sesiones es de 90 minutos a 120 minutos. Al finalizar, el programador recibe la lista con los errores para corregirlos, se actualiza la lista si es necesario y luego de corregidos los errores, se realiza otra ronda de inspección.

Tipos de problemas que se buscan (checklist): Errores en la referencia de datos, errores de declaración de datos, errores de computación (variables mal definidas: tipo, longitud, etc.), errores de comparación, errores de flujo de control, errores de interfaz (una de las preguntas que se podría hacer es: ¿Es igual el número de parámetros recibidos por un módulo al número de argumentos enviados por cada uno de los módulos que llaman? ¿Es el orden correcto? y errores de E/S.

Las Recorridas (walkthroughs) de codificaciones son muy parecidas a las inspecciones, la diferencia está en la técnica de detección de errores. En este procedimiento, a diferencia de las Inspecciones, en lugar de usarse una lista (checklist) o leer simplemente el programa durante las reuniones, la persona designada como tester o probador, concurre a la reunión con una serie de casos de prueba con los datos de entrada y los resultados esperados.

Cada caso de prueba se ejecuta manualmente, es decir, el caso de prueba es pasado a través de la lógica del programa y se registra el estado del mismo (es decir los valores de las variables) en papel o en una pizarra. Por supuesto, los casos de prueba deben ser de naturaleza simple y pocos en número, ya que el hombre “ejecuta” los programas a una velocidad que es en muchos aspectos de magnitud inferior a la máquina.

Punto 4 - Estructuración del proceso de prueba

Dadas las limitaciones existentes en tiempo, costos, recursos, la cuestión clave referente a las pruebas de un programa es:

¿Cuál es el subconjunto de todos los posibles casos de prueba que tiene la mayor probabilidad de detectar el mayor número posible de errores?

El autor sugiere como estrategia razonable de prueba, la utilización de métodos de pruebas de caja negra, desarrollando adicionalmente casos suplementarios basados en los métodos de caja blanca, ya que cada uno de ellos tiene fuerzas y debilidades particulares.

Por otra parte, no es lo mismo probar un programa de 100 líneas de código, que uno de más de 500 líneas, o un sistema grande, complejo, y con variadas interfaces con otros sistemas.
Por lo tanto, se puede pensar la prueba por módulos, y avanzar luego en integración de los mismos.

Lista de pruebas a planificar: Pruebas de módulos (caja blanca), pruebas de función (caja negra), pruebas de sistema (sentencias, volumen, usabilidad, seguridad, tiempo de respuesta, almacenamiento, recuperación, etc.), pruebas de aceptación y pruebas de instalación.

Punto 5 - Planificación y control, finalización de las prueba

Ante un sistema grande se puede estar frente un enorme problema de Planificación, observación y control de un proceso de prueba que puede involucrar la escritura, ejecución y verificación de decenas de miles de casos de prueba, el manejo de miles de módulos, la corrección de miles de errores y el empleo quizás de cientos de personas en uno u otro momento durante el lapso de un año o más.

El mayor error cometido en la planificación de un proceso de prueba ha sido ya mencionado en el Punto 1; es la tácita suposición hecha cuando se establece un cronograma, de que no se encontrarán errores. El resultado obvio de esta equivocación es que los recursos planeados (gente, tiempo de calendario y tiempo de máquina) serán groseramente subestimados. Contribuye a esto el hecho de que los procesos de prueba suelen efectuarse hacia el final del ciclo del desarrollo, lo que hace que las modificaciones de recursos sean difíciles de lograr.

Como en la mayoría de los proyectos, la planificación es una parte decisiva de la organización del proceso de prueba. Los componentes de un buen plan son:

1. Objetivos

2. Criterios de terminación

3. Cronograma

4. Responsabilidades

5. Biblioteca de casos de pruebas y normas.

6. Herramientas.

7. Tiempo de máquina.

8. Configuración del equipo

9. Integración

10. Métodos de Seguimiento

11. Procedimientos para eliminación de fallas (debugging)

12. Pruebas de deterioro o regresión

Una de las preguntas más difíciles de responder cuando se realizan pruebas de programas es cuándo dar ésta por terminada, puesto que no hay manera de saber si el último error detectado es el único que quedaba.

En vista a este dilema y de que la economía es quien dictamina que la prueba debe darse por terminada, existen criterios útiles para definir la terminación de la prueba. Existen tres categorías de criterios de mayor utilidad. La primer categoría, aunque no la mejor, es basar la terminación en el uso de métodos específicos de diseño de casos de prueba.

La segunda categoría de criterios, y quizás la más valiosa, es establecer los requerimientos de determinación en términos positivos, es decir detectar un número predefinido de errores.

El tercer criterio consiste en representar gráficamente el número de errores encontrados por unidad de tiempo durante la fase de pruebas. Supóngase que se está realizando pruebas de función sobre un programa y se grafica el número de errores encontrados por semana, si en la séptima semana la curva tiene el aspecto de la figura de la izquierda entonces será imprudente terminar la prueba, por otra parte la curva obtenida en el gráfico de la derecha la detección de errores ha bajado significativamente, lo que implica que, quizá, la prueba de función ha cumplido ya su cometido y que es posible terminar con las pruebas de función y comenzar otras por ejemplo de sistemas.

- Gráficos con estimaciones del momento apropiado para dar las pruebas por terminadas mediante gráficos de errores detectados por unidad de tiempo

image
El mejor criterio para determinar si las pruebas se pueden dar por terminado es, probablemente una combinación de los tres tipos de pruebas ya mencionas más arriba en el Punto 4, tomando para cada una algunos de los criterios mencionados.

Algunas conclusiones

Dada la época en que fue escrito el libro, el modelo que describe no hace referencia a métodos ágiles, al menos por su nombre, si bien ya había algunos intentos por esos años.

De cualquier modo, parte de las prácticas son útiles, en función a la misión que el equipo de pruebas tenga que cumplir. Ver también: http://excelza.blogspot.com/2009/10/sobre-nuestra-mision-como-testers.html.

Cómo vemos hoy estos puntos enunciados por Myers?:

Punto 1 - Qué es probar: Probar es demostrar que los interesados pueden utilizar el producto adecuadamente según sus necesidades y requisitos. Actualmente la complejidad de las plataformas de hardware y software, la interacción e interconexión de los productos y sistemas, y por qué no, Internet y el cloud computing, hacen imprescindible fijar al inicio los objetivos de las pruebas, identificar a los interesados, sus necesidades y requisitos, en todos los órdenes, tanto “utilidad” como “garantía”. Todo esto permitirá determinar los procedimientos de prueba a aplicar, los riesgos a mitigar con las pruebas, los oráculos a consultar respecto a los resultados esperados, y a quiénes y cuándo informar resultados obtenidos, e impactará en las decisiones que se tomen en relación a cada uno de los puntos siguientes:

Punto 2 - Principios fundamentales: Siguen en general vigentes. Hay discusión respecto a la necesidad o no de escritura detallada de los casos de prueba, testing exploratorio, y otras técnicas.

Punto 3 - Probar tempranamente: Es siempre discutido y discutible. Si bien conceptualmente es aplicable, la complejidad y dinamismo de los desarrollos en la actualidad hacen que se utilicen poco las Inspecciones y Recorridas, por los tiempos de respuesta que se requieren.

Punto 4 - Estructuración del proceso de prueba: Sigue vigente. Como se dijo en el Punto 1, hay necesidad de planificar y ejecutar distintos tipos de pruebas según los objetivos, estrategias, tipos de proyectos, metodologías de construcción aplicadas, tipos de productos, características de la organización, etc... .
Ver también: http://excelza.blogspot.com/2009/11/pensando-que-probar.html.

Punto 5 - Planificación y control, finalización de las prueba: Sigue vigente. Con mucho más foco en análisis de riesgos, atributos de calidad requeridos, y “good enough quality”. Los planes específicos deben embeberse en los planes de prueba de los servicios de los que el software forma parte, ya que las aplicaciones que contribuyen a la arquitectura del servicio, tienen que tener funcionalidad y no funcionalidad tales, que el servicio pueda proveer la utilidad y garantía acordada con el cliente. Ver también: http://excelza.blogspot.com/2009/12/sobre-pruebas-de-software-y-servicios.html.

Hasta la próxima!

4 comentarios:

  1. Excelente articulo. Claro, sencillo y didactico.

    ResponderEliminar
  2. David Rodríguez Saravia6 de marzo de 2010, 21:58

    Muy buen articulo, gracias

    ResponderEliminar