jueves, 21 de febrero de 2008

Pruebas del sistema

Las pruebas del sistema

Si bien en la práctica los términos se manejan en forma intercambiable, técnicamente debemos distinguir entre las pruebas del software completo (pruebas de verificación de requerimientos) y las pruebas del sistema que incorpora el software (pruebas del sistema o pruebas de validación del sistema). En el contexto de este curso atenderemos fundamentalmente las pruebas de verificación.
El objetivo de las pruebas de verificación es buscar discrepancias entre los requerimientos y la ejecución del software.
Recuerde, de Sistemas de Programas, que probar es la actividad dedicada a encontrar posibles defectos en un producto, no es determinar que un producto funcione. [¿Por qué? Repasar barrera psicológica: el tester como médico diagnosticante].
El proceso de verificación de los requerimientos comienza con el análisis de esos requerimientos y una inspección en la cual se busca evaluar la consistencia, completitud y factibilidad de los requerimientos, tanto individualmente como juntos. Adicionalmente los requerimientos deben ser revisados y validados por los distintos actores involucrados con el sistema (stakeholders), acción que debe aclarar los compromisos al respecto, tanto en el sentido de trade-offs (prioridades y balance) entre requerimientos como en en el sentido de commitments (compromisos que asumen los actores).
Para evitar sorpresas de variada índole a la hora de entregar el software, es conveniente especificar claramente qué vamos a hacer para determinar que el sistema satisface sus requerimientos. Por ejemplo, no basta con decir que un sistema será amigable o fácil de usar, ¿cómo se medirá o verificará que el software es amigable?
Estas especificaciones son cruciales a la hora de diseñar las pruebas de verificación. Note que el diseño de estas pruebas requiere los siguientes pasos:
Revisar la verificabilidad del requerimiento;
Especificar el criterio de verificación;
Hacer visible las propiedades o elementos del software necesarios para verificar el cumplimiento del requerimiento;
Hacer controlable los elementos del software necesarios para llevar a cabo las pruebas;
Elaborar el plan de pruebas;
Ejecutar el plan de pruebas y reportar sus resultados.
Ejemplo:Tomemos un requerimiento de un software, tal como un atributo de desempeño. La discusión anteriores nos conduce a los siguientes pasos:
Revisar la verificabilidad del atributo. Supongamos que el atributo restringe el tiempo de respuesta del software.
Especificar el criterio. Este puede darse en términos absolutos ("el sistema debe responder a cualquier comando en menos de 2 segundos") o relativos a un modelo de desempeño.
Para hacer observable la propiedad que nos interesa (tiempo de respuesta) tendremos que instrumentar el software o utilizar un ambiente de ejecución que permita obtener los tiempos que nos interesan.
Para controlar el software, necesitamos poder variar los valores de las entradas al sistema, así como otros elementos como (posiblemente) el estado del software y la tasa, velocidad o distribución de presentación de esas entradas. Para ello puede ser que necesitemos escribir monitores, simuladores o manejadores. Pospondremos la discusión de los dos últimos pasos.

Prueba de caja negra

Pruebas de caja negra
Tome usted la especificación del programa o, en su defecto, el manual de usuario. Uno u otro determinan "lo que el programa tiene que hacer". Y haga al menos una prueba de todas y cada una de las cosas que el programa tiene que hacer.
Si va usa un marcador fosforescente para señalar los párrafos que va verificando que funcionan correctamente, llegará un momento que todo el manual está marcado como "ejecuta correctamente". En la jerga de pruebas se dice que ha conseguido una cobertura funcional del 100%.
Es casi imprescindible lograr una cobertura de caja negra del 100%, pues los usuarios se quejarían con todo derecho de fallos de este calibre. O, en términos académicos, el profesor tiene todo el derecho a penalizar un programa que no hace lo que tiene que hacer.

caja blanca

Caja blancaSinónimos:
pruebas estructurales
pruebas de caja transparente

En estas pruebas estamos siempre observando el código, que las pruebas se dedican a ejecutar con ánimo de "probarlo todo". Esta noción de prueba total se formaliza en lo que se llama "cobertura" y no es sino una medida porcentual de ¿cuánto código hemos cubierto?

Hay diferentes posibilidades de definir la cobertura. Todas ellas intentan sobrevivir al hecho de que el número posible de ejecuciones de cualquier programa no trivial es (a todos los efectos prácticos) infinito. Pero si el 100% de cobertura es infinito, ningún conjunto real de pruebas pasaría de un infinitésimo de cobertura. Esto puede ser muy interesante para los matemáticos; pero no sirve para nada.

Cobertura de segmentos
A veces también denominada "cobertura de sentencias". Por segmento se entiende una secuencia de sentencias sin puntos de decisión. Como el ordenador está obligado a ejecutarlas una tras otra, es lo mismo decir que se han ejecutado todas las sentencias o todos los segmentos.
El número de sentencias de un programa es finito. Basta coger el código fuente e ir contando. Se puede diseñar un plan de pruebas que vaya ejercitando más y más sentencias, hasta que hayamos pasado por todas, o por una inmensa mayoría.
En la práctica, el proceso de pruebas termina antes de llegar al 100%, pues puede ser excesivamente laborioso y costoso provocar el paso por todas y cada una de las sentencias.
A la hora de decidir el punto de corte antes de llegar al 100% de cobertura hay que ser precavido y tomar en consideración algo más que el índice conseguido. En efecto, ocurre con harta frecuencia que los programas contienen código muerto o inalcanzable. Puede ser que este trozo del programa, simplemente "sobre" y se pueda prescindir de él; pero a veces significa que una cierta funcionalidad, necesaria, es inalcanzable: esto es un error y hay que corregirlo.
Cobertura de ramas
La cobertura de segmentos es engañosa en presencia de segmentos opcionales. Por ejemplo:
IF Condicion THEN EjecutaEsto; END;
Desde el punto de vista de cobertura de segmentos, basta ejecutar una vez, con éxito en la condición, para cubrir todas las sentencias posibles. Sin embargo, desde el punto de vista de la lógica del programa, también debe ser importante el caso de que la condición falle (si no lo fuera, sobra el IF). Sin embargo, como en la rama ELSE no hay sentencias, con 0 ejecuciones tenemos el 100%.
Para afrontar estos casos, se plantea un refinamiento de la cobertura de segmentos consistente en recorrer todas las posibles salidas de los puntos de decisión. Para el ejemplo de arriba, para conseguir una cobertura de ramas del 100% hay que ejecutar (al menos) 2 veces, una satisfaciendo la condición, y otra no.
Estos criterios se extienden a las construcciones que suponen elegir 1 de entre varias ramas. Por ejemplo, el CASE.
Nótese que si lograramos una cobertura de ramas del 100%, esto llevaría implícita una cobertura del 100% de los segmentos, pues todo segmento está en alguna rama. Esto es cierto salvo en programas triviales que carecen de condiciones (a cambio, basta 1 sóla prueba para cubrirlo desde todos los puntos de vista). El criterio también debe refinarse en lenguajes que admiten excepciones (por ejemplo, Ada). En estos casos, hay que añadir pruebas para provocar la ejecución de todas y cada una de las excepciones que pueden dispararse.