Pruebas en el desarrollo de software

Prueba de Programas

 

1.      Introducción

Una de las últimas fases del ciclo de vida antes de entregar un programa para su explotación, es la fase de pruebas.

Pese a su enorme impacto en el coste de desarrollo, es una fase que muchos programadores aún consideran clasificable como un arte y, por tanto, como difícilmente conceptualizable.

¿Qué es probar?

El objetivo específico de la fase de pruebas es encontrar cuantos más errores, mejor.

La Prueba Exhaustiva es Imposible:

Esto es imposible desde todos los puntos de vista: humano, económico e incluso matemático.

Organización

Hay multitud de conceptos (y palabras clave) asociadas a las tareas de prueba. Clasificarlas es difícil, pues no son mutuamente disjuntas, sino muy entrelazadas.

 

2.      Prueba de Unidades

CAJA NEGRA.

Este es el primer acercamiento del Ingeniero de Pruebas a la aplicación, en donde se prueba que todos los requerimientos funcionales del documento de Feature Proposal estén incluidos y que funcionalmente cumplan con las especificaciones. En este punto el Ingeniero de pruebas recorre punto por punto la aplicación buscando fallas.

CAJA BLANCA.

En un segundo acercamiento el Ingeniero de Pruebas además de asegurar que la aplicación funcione correctamente, también se asegura que todos los datos que la aplicación debe registrar en la capa de datos existan y sean coherentes.

PRUEBA ESTRUCTURAL.

Para el caso de las aplicaciones, en el ambiente de producción el Ingeniero de Pruebas realiza las pruebas de caja blanca y caja negra sobre la aplicación que se encuentra montada en el servidor interno asegurando que estructuralmente la aplicación no tenga ninguna falencia.

 

PRUEBAS DE CÓMPUTO.

Las aplicaciones manejan gran cantidad de información y realizan operaciones de cómputo, para calcular algunos datos y agrupación de registros, por lo tanto el Ingeniero de Pruebas enfatiza en estos aspectos y verifica que las operaciones sean consistentes, verificando así mismo los reportes buscando incongruencias.

 

PRUEBA NEGATIVA.

Se realizan pruebas de longitud y tipo de datos que se ingresan en los formularios, verificando que se muestren al usuario los mensajes correspondientes para que pueda modificar los datos ingresados. Un ejemplo de esto lo tenemos en la ventana de ingreso donde se debe digitar el usuario y la contraseña que deben cumplir ciertas características especiales, si el usuario ingresa algún dato de manera incorrecta, la aplicación le mostrara los mensajes necesarios para que pueda corregir lo valores ingresados o tendrá mensajes que le informan su estado dentro del sistema. Al ser una aplicación web el usuario no tendrá acceso a la configuración de la misma por lo tanto el nivel de operabilidad de la aplicación dependerá totalmente del administrador del servidor donde se encuentre instalada.

 

 

3.      Pruebas de Integración

Las pruebas estructurales de integración son similares a las pruebas de caja blanca; pero trabajan a un nivel conceptual superior. En lugar de referirnos a sentencias del lenguaje, nos referiremos a llamadas entre módulos. Se trata pues de identificar todos los posibles esquemas de llamadas y ejercitarlos para lograr una buena cobertura de segmentos o de ramas.

Las pruebas finales de integración cubren todo el sistema y pretenden cubrir plenamente la especificación de requisitos del usuario. Además, a estas alturas ya suele estar disponible el manual de usuario, que también se utiliza para realizar pruebas hasta lograr una cobertura aceptable.

 

4.      Pruebas de Aceptación

Estas pruebas las realiza el cliente. Son básicamente pruebas funcionales, sobre el sistema completo, y buscan una cobertura de la especificación de requisitos y del manual del usuario. Estas pruebas no se realizan durante el desarrollo, pues sería impresentable de cara al cliente; sino una vez pasada todas las pruebas de integración por parte del desarrollador.

 

5.      Otros tipos de Pruebas

Recorridos (walkthroughs)

Quizás es una técnica más aplicada en control de calidad que en pruebas. Consiste en sentar alrededor de una mesa a los desarrolladores y a una serie de críticos, bajo las órdenes de un moderador que impida un recalentamiento de los ánimos. El método consiste en que los revisores se leen el programa línea a línea y piden explicaciones de todo lo que no está meridianamente claro. Puede que simplemente falte un comentario explicativo, o que detecten un error auténtico o que simplemente el código sea tan complejo de entender/explicar que más vale que se rehaga de forma más simple. Para un sistema complejo pueden hacer falta muchas sesiones.

Aleatorias (random testing)

Ciertos autores consideran injustificada una aproximación sistemática a las pruebas. Alegan que la probabilidad de descubrir un error es prácticamente la misma si se hacen una serie de pruebas aleatoriamente elegidas, que si se hacen siguiendo las instrucciones dictadas por criterios de cobertura (caja negra o blanca).

Como esto es muy cierto, probablemente sea muy razonable comenzar la fase de pruebas con una serie de casos elegidos al azar. Esto pondrá de manifiesto los errores más patentes. No obstante, pueden permanecer ocultos errores más sibilinos que sólo se muestran ante entradas muy precisas.

Aguante (stress testing)

En ciertos sistemas es conveniente saber hasta dónde aguantan, bien por razones internas (¿hasta cuantos datos podrá procesar?), bien externas (¿es capaz de trabajar con un disco al 90%?, ¿aguanta una carga de la CPU del 90?, etc)

Prestaciones (performance testing)

A veces es importante el tiempo de respuesta, u otros parámetros de gasto. Típicamente nos puede preocupar cuánto tiempo le lleva al sistema procesar tantos datos, o cuánta memoria consume, o cuánto espacio en disco utiliza, o cuántos datos transfiere por un canal de comunicaciones, o … Para todos estos parámetros suele ser importante conocer cómo evolucionan al variar la dimensión del problema (por ejemplo, al duplicarse el volumen de datos de entrada).

 

6.      Depuración

Casi todos los compiladores suelen llevar asociada la posibilidad de ejecutar un programa paso a paso, permitiéndole al operador conocer dónde está en cada momento, y cuánto valen las variables.

Los depuradores pueden usarse para realizar inspecciones rigurosas sobre el comportamiento dinámico de los programas. La práctica demuestra, no obstante, que su uso es tedioso y que sólo son eficaces si se persigue un objetivo muy claro. El objetivo habitual es utilizarlo como consecuencia de la detección de un error. Si el programa se comporta mal en un cierto punto, hay que averiguar la causa precisa para poder repararlo.

 

7.      Plan de Pruebas

Un plan de pruebas está constituido por un conjunto de pruebas. Cada prueba debe

· dejar claro qué tipo de propiedades se quieren probar (corrección, robustez, fiabilidad, amigabilidad, …)

·         dejar claro cómo se mide el resultado

·         especificar en qué consiste la prueba (hasta el último detalle de cómo se ejecuta)

·         definir cuál es el resultado que se espera (identificación, tolerancia, …) ¿Cómo se decide que el resultado es acorde con lo esperado?

Las pruebas angelicales carecen de utilidad, tanto si no se sabe exactamente lo que se quiere probar, o si no está claro cómo se prueba, o si el análisis del resultado se hace "a ojo".

Estas mismas ideas se suelen agrupar diciendo que un caso de prueba consta de 3 bloques de información:

1.      El propósito de la prueba

2.      Los pasos de ejecución de la prueba

3.      El resultado que se espera

 

8.      Aspectos a Tener en cuenta

·        Probar es ejercitar un programa para encontrarle fallos.
Jamás se debería probar un programa con el ánimo de mostrar que funciona; ese no es el objetivo.

·        Un caso de prueba tiene éxito cuando encuentra un fallo.
Lo gracioso no es encontrar un caso en el que el programa funciona perfectamente. Eso es, simplemente, lo normal. Lo guai es encontrar el caso en el que falla.

·        Las pruebas debe diseñarlas y pasarlas una persona distinta de la que ha escrito el código; es la única forma de no ser "comprensivo con los fallos".

o      Hacer una "obra maestra" cuesta mucho esfuerzo y requiere gran habilidad. Encontrarle fallos a una "obra maestra" cuesta aún más esfuerzo y exige otro tipo de habilidad.

·        Las pruebas no pueden esperar a que esté todo el código escrito para empezar a pasarlas. Deben irse pasando pruebas según se va generando el código para descubrir los errores lo antes posible y evitar que se propaguen a otros módulos. En realidad el nombre "fase de pruebas" es engañoso, pues hay muchas actividades que se desarrollan concurrentemente o, al menos, no se necesita cerrar una fase antes de pasar a la siguiente. Algunos autores llegan al extremo de afirmar que "primero hay que probar y luego codificar". Frase graciosa que se plasma en aspectos más concretos como que el programa se escriba pensando en que hay que probarlo.

·        Si en un módulo (o sección de un programa, en general) se encuentran muchos fallos, hay que insistir sobre él. Es muy habitual que los fallos se concentren en pequeñas zonas. Hay mil causas para que ocurra este efecto:

o      código escrito por un programador malo

o      código muy difícil

o      código mal o insuficientemente especificado

o      código escrito en un mal día, con prisas, …

o      Además, cuanto más se parchea un trozo de código, tanto más ruinoso queda y susceptible a derrumbamientos. A la larga hay que acabar tirándolo y empezando de nuevo.

·        Si se detecta un fallo aislado, puede bastar una corrección aislada. Pero si se detectan muchos fallos en un módulo, lo único práctico es desecharlo, diseñarlo de nuevo, y recodificarlo. La técnica de ir parcheando hasta que se pasan una serie de pruebas es absolutamente suicida y sólo digna del avestruz.

·        Las pruebas pueden encontrar fallos; pero jamás demostrar que no los hay.

·        Las pruebas también tienen fallos. Los errores son propios de los humanos: todo el mundo se equivoca. Si una prueba falla, hay que revisar tanto lo que se prueba como lo que lo prueba. No obstante, la experiencia muestra que (casi siempre) hay más fallos el probado que en el probador.

Conclusiones

·        Probar es buscarle los fallos a un programa.

·        La fase de pruebas absorbe una buena porción de los costes de desarrollo de software. Además, se muestra renuente a un tratamiento matemático o, simplemente, automatizado.

·        Aunque se han desarrollado miles de herramientas de soporte de esta fase, todas han limitado su éxito a entornos muy concretos, frecuentemente sólo sirviendo para el producto para el que se desarrollaron.

·        El objetivo de las pruebas es encontrar defectos

·        Se puede validar todos los artefactos

·        Como buena práctica se debe realizar pruebas frecuentemente y de manera temprana

 

 

Bibliografía

http://www.lab.dit.upm.es/~lprg/material/apuntes/pruebas/testing.htm#s21

 

http://www.agilemodeling.com/essays/modelReviews.htm

 

 

About omaracostacasas

ING SOFTWARE
This entry was posted in Ingenieria de Software. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s