lunes, 7 de junio de 2010

Que es un proceso de pruebas


Un proceso puede ser definido como un conjunto de actividades enlazadas entre sí que, partiendo de una o más entradas los transforma, generando un resultado.

Un proceso de pruebas de software estará conformado por un criterio de entrada y un criterio de salida.

Criterio de Entrada: Necesidad de Pruebas de Software.
Criterio Salida:Respuesta a las no conformidades.

Los procesos de pruebas varían en dependencia de la organización,no todas las organizaciones tiene que tener el mismo proceso de pruebas, depende de las características específicas de cada entidad.

Se va a tener como atributo los Roles,la Entrada,las Actividades y Salida.

-Los Roles van en dependencia de la metodología a utilizar en la entidad.
-Como entradas vamos a tener los siguientes artefactos:Necesidad de Pruebas,Especificación de Requisitos,Especificación de Casos de Uso,Guá de los tipos de pruebas, elementos a probar,documento de bugs detectados.
-Entre las actividades podemos encontrar: Establecer objetivos de las pruebas,Planificar Pruebas,Especificación de Casos de Pruebas/Diseño,Ejecución de las pruebas y Análisis y reporte de los resultados.
-En los artefactos de salida tendremos: Plan de Pruebas,Diseño de Pruebas,Listas de Chequeo, Documento de Bugs detectados, Documento Respuestas a los Bugs detectados.

Decir que en un proceso de pruebas tanto como las actividades, los roles, los artefactos de entrada y los artefactos de salida dependen gradualmente del negocio y políticas de la entidad.

La imagen que aquí les muestro es solo un ejemplo de como podrán elaborar un proceso de pruebas.

Competencias del Probador

Conocimientos:
-Ingeniería de Software( Capaz de identificar el momento en el que se desarrollan las pruebas teniendo en cuenta la metodología que se sigue para el desarrollo. Capaz de utilizar los diseños de casos de uso del sistema y especificación de requisitos para tributar a los diseños de prueba Capacidad de entender el negocio. )
-Documentación de las pruebas( Capaz de documentar y comunicar los errores encontrados en las pruebas )
-Identificación de errores( Registrar y analizar salida de las pruebas )
-Tipos de pruebas( Ha realizado algún tipo de pruebas (ejemplo: pruebas de sistema, funcionalidad, integración). Capaz de reconocer diferentes técnicas de pruebas y utilizar la más eficiente dependiendo del producto. )
-Herramientas( Implementa el uso de al menos una herramienta para la realización de las pruebas de forma automática )

Aplicación:
-Planificar y gestionar las pruebas( Capaz de planificar la realización de las pruebas a lo largo del ciclo de vida del software. Evaluar el avance de las pruebas y los tiempos incurridos. Capaz de desarrollar y actualizar el plan de pruebas. )
-Diseño de Casos de pruebas( Capaz de diseñar casos de prueba para los casos de uso del sistema y/o requisitos. )
-Aplicar Diseño de pruebas( Capaz de entender y aplicar al sistema diseños de casos de prueba de forma correcta. )
-Pruebas automáticas( Capaz de hacer pequeños programas para probar software (ejemplo: pruebas de unidad para pequeñas unidades de código) )
-Resultado de las pruebas( Capaz de hacer reporte de resultado de las pruebas en el documento de no conformidades.Capaz de comunicar resultados de las pruebas a través de tickets. )

Experiencia:
-Relación de pruebas( Presenta un trabajo continuado en la realización de pruebas. )
-Años de experiencia(1 a 2)



Técnica o Pruebas de Caja Negra

Son complementarias a las de caja blanca. Pero en la práctica se hace normalmente solo la prueba de caja negra.

Errores habituales que se encuentran con pruebas de caja negra:
*Funciones inexistentes o incorrectas.
*Errores de interfase.
*Errores de iniciación, comienzo o finalización.
*Errores de rendimiento.

La prueba de caja negra responde a las preguntas:
*Que casos de entrada terminan definiendo buenos casos de prueba.
*Si el sistema es sensible a determinados casos de entrada.
*Que volúmenes (niveles de datos) tolera el sistema.

Planteamos 2 técnicas:

1)- Análisis de Valores Límites:
Pressman dice que no hay una identificación clara de los valores límite, dice que suele haber más errores en los valores límites que en los típicos.
Cuando hablamos de Valores Limites lo que decimos es que elegimos casos de prueba en los límites o bordes de la clase que estamos probando. (Ej.: Si una condición de entrada o salida exige un rango entre B y R, se realizan los casos de prueba para los valores B y R, y además a los valores que están por encima de ellos, es decir A y S).

2)- Partición Equivalente:
Es una técnica de simplificación de pruebas.
Hay que dividir el dominio de entrada de un programa en clases de datos que tengan algo en común, de ahí derivan clases de prueba y por lo tanto también derivan clases de errores, de esta forma no hay necesidad de ejecutar muchas pruebas para encontrar errores genéricos.

Para lograr esta se evalúan las clases de equivalencias posibles para una condición de entrada.

Clases de equivalencias: Son los conjuntos de estados (válidos o no) para las condiciones de entrada.

Condiciones de entrada: Valor numérico, rango de valores, condición booleana (si o no).

- Si una condición de entrada especifica un rango, se propone definir una clase de equivalencia valida y 2 inválidas.
- Si una condición de entrada especifica un número, un valor, se define una clase de equivalencia igual al caso anterior, (1 valida y 2 inválidas).
- Si una condición de entrada especifica un miembro de un conjunto, se define una condición valida y una invalida.
- Si es booleana, se define una clase de equivalencia igual al caso anterior (1 valida y 1 inválida).

Pruebas Caja Blanca(Método Coberturas)

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?

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 lográramos 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.

Cobertura de condición/decisión:

La cobertura de ramas resulta a su vez engañosa cuando las expresiones booleanas que usamos para decidir por qué rama tirar son complejas. Por ejemplo:

IF Condicion1 OR Condicion2 THEN HazEsto; END;

Si el programa contiene bucles LOOP, o simplemente bucles con trampa, la única cobertura aplicable es la de ramas. El riesgo de error es muy alto; pero no se conocen técnicas sistemáticas de abordarlo, salvo reescribir el códigos condiciones 1 y 2 pueden tomar 2 valores cada una, dando lugar a 4 posibles combinaciones. No obstante sólo hay dos posibles ramas y bastan 2 pruebas para cubrirlas. Pero con este criterio podemos estar cerrando los ojos a otras combinaciones de las condiciones.

Consideremos sobre el caso anterior las siguientes pruebas:

Prueba 1: Condicion1 = TRUE y Condicion2 = FALSE
Prueba 2: Condicion1 = FALSE y Condicion2 = TRUE
Prueba 3: Condicion1 = FALSE y Condicion2 = FALSE
Prueba 4: Condicion1 = TRUE y Condicion2 = TRUE

Bastan las pruebas 2 y 3 para tener cubiertas todas las ramas. Pero con ellos sólo hemos probado una posibilidad para la Condición1.

Para afrontar esta problemática se define un criterio de cobertura de condición/decisión que trocea las expresiones booleanas complejas en sus componentes e intenta cubrir todos los posibles valores de cada uno de ellos.

Nótese que no basta con cubrir cada una de las condiciones componentes, si no que además hay que cuidar de sus posibles combinaciones de forma que se logre siempre probar todas y cada una de las ramas. Así, en el ejemplo anterior no basta con ejecutar las pruebas 1 y 2, pues aun cuando cubrimos perfectamente cada posibilidad de cada condición por separado, lo que no hemos logrado es recorrer las dos posibles ramas de la decisión combinada. Para ello es necesario añadir la prueba 3.

El conjunto mínimo de pruebas para cubrir todos los aspectos es el formado por las pruebas 3 y 4. Aún así, nótese que no hemos probado todo lo posible. Por ejemplo, si en el programa nos colamos y ponemos AND donde queríamos poner OR (o viceversa), este conjunto de pruebas no lo detecta. Sólo queremos decir que la cobertura es un criterio útil y práctico; pero no es prueba exhaustiva.

Cobertura de bucles:

Los bucles no son más que segmentos controlados por decisiones. Así, la cobertura de ramas cubre plenamente la esencia de los bucles. Pero eso es simplemente la teoría, pues la práctica descubre que los bucles son una fuente inagotable de errores, todos triviales, algunos mortales. Un bucle se ejecuta un cierto número de veces; pero ese número de veces debe ser muy preciso, y lo más normal es que ejecutarlo una vez de menos o una vez de más tenga consecuencias indeseables. Y, sin embargo, es extremadamente fácil equivocarse y redactar un bucle que se ejecuta 1 vez de más o de menos.

Para un bucle de tipo WHILE hay que pasar 3 pruebas

1. 0 ejecuciones
2. 1 ejecución
3. más de 1 ejecución

Para un bucle de tipo REPEAT hay que pasar 2 pruebas

1. 1 ejecución
2. más de 1 ejecución

Los bucles FOR, en cambio, son muy seguros, pues en su cabecera está definido el número de veces que se va a ejecutar. Ni una más, ni una menos, y el compilador se encarga de garantizarlo. Basta pues con ejecutarlos 1 vez.

No obstante, conviene no engañarse con los bucles FOR y examinar su contenido. Si dentro del bucle se altera la variable de control, o el valor de alguna variable que se utilice en el cálculo del incremento o del límite de iteración, entonces eso es un bucle FOR con trampa.

También tiene "trampa" si contiene sentencias del tipo EXIT (que algunos lenguajes denominan BREAK) o del tipo RETURN. Todas ellas provocan terminaciones anticipadas del bucle.

Estos últimos párrafos hay que precisarlos para cada lenguaje de programación. Lo peor son aquellos lenguajes que permiten el uso de sentencias GOTO. Tampoco conviene confiarse de lo que prometen lenguajes como MODULA-2, que se supone que prohíben ciertas construcciones arriesgadas. Los compiladores reales suelen ser más tolerantes que lo que anuncian los libros.

Si el programa contiene bucles LOOP, o simplemente bucles con trampa, la única cobertura aplicable es la de ramas. El riesgo de error es muy alto; pero no se conocen técnicas sistemáticas de abordarlo, salvo reescribir el código.

domingo, 6 de junio de 2010

Pruebas de Unidad

Aplicar Pruebas de Unidad a un sistema existente será difícil. Si el sistema es mediano o grande, es conveniente planear sus pruebas y aplicar los cambios necesarios a través de varias versiones futuras. Las pruebas unitarias aíslan cada parte del programa y muestran que las partes individuales son correctas. A pesar de esto no descubrirán todos los errores del código, no descubren errores de integración, de rendimiento ni otros problemas que afectan a todo el sistema en su conjunto.


Las pruebas de unidad están divididas en dos grupos, en Pruebas de Caja Blanca y Pruebas de Caja Negra.


En las pruebas de Caja Blanca se observa siempre el código, las mismas se realizan para probarlo todo. Estas pruebas se aplican mediante diferentes métodos.


-Prueba de Condición: Es un método de diseño de casos de prueba que ejercita las condiciones lógicas contenidas en el módulo de un programa.


-Prueba de Flujo de Datos: Es un método en el que se seleccionan caminos de prueba de un programa de acuerdo con la ubicación de las definiciones y los usos de las variables del programa.


-Prueba de Bucles: Es una técnica de prueba de caja blanca que se centra exclusivamente en la validez de las construcciones de bucles.


-Prueba del Camino Básico: Esta permite al diseñador de casos de prueba obtener una medida de la complejidad lógica de un diseño procedimental y usar esa medida como guía para la definición de un conjunto básico de caminos de ejecución.


Las pruebas de Caja Blanca verifican la implementación interna de la unidad. Para cada componente se estudiará su implementación interna y se tratará de verificar su correcto comportamiento algorítmico. Se comprobarán los caminos comunes, los críticos, los menos conocidos y otros asociados con riesgos altos. Lograr un buen método con pruebas de caja blanca es un objetivo deseable pero no suficiente a todos los efectos. Un programa puede estar perfecto en todos sus términos y sin embargo no servir a la función que se pretende.


Por su parte, las pruebas de caja negra se centran en lo que se espera de un módulo, es decir, intentan encontrar casos en que el módulo no se atiene a su especificación. Por ello se denominan pruebas funcionales y el probador se limita a suministrarle datos como entrada y estudiar la salida, sin preocuparse de lo que pueda estar haciendo el módulo por dentro.


Las pruebas de Caja Negra están especialmente indicadas en aquellos módulos que van a ser interfaz con el usuario (ejemplo: canales de comunicaciones, etc.). Estas pruebas verifican el comportamiento de la unidad observable externamente. Cuando el número de entradas y salidas es grande, se dividen estas en clases de equivalencias. Una clase de equivalencia es un conjunto de valores de entradas o salidas para los que se supone que un componente se comporta de forma similar.


El problema con las pruebas de caja negra no suele estar en el número de funciones proporcionadas por el módulo (que siempre es un número muy limitado en diseños razonables) sino en los datos que se le pasan a estas funciones. El conjunto de datos posibles suele ser muy amplio (por ejemplo, un entero).


Durante la lectura de los requisitos del sistema, se pueden encontrar una serie de valores singulares que marcan diferencias de comportamiento. Estos valores son claros candidatos a marcar clases de equivalencia: por abajo y por arriba.


Una vez identificadas las clases de equivalencia significativas en dicho módulo, se procede a coger un valor de cada clase, que no esté justamente al límite de la clase. Este valor aleatorio, sustituye a cualquier valor normal que se le pueda pasar en la ejecución real.


La experiencia muestra que un buen número de errores aparecen en torno a los puntos de cambio de clase de equivalencia. Hay una serie de valores denominados "frontera" (o valores límite) que conviene probar, además de los elegidos en el párrafo anterior. Usualmente se necesitan 2 valores por frontera, uno justo abajo y otro justo encima.


Las pruebas de caja negra convencen de que un programa hace lo que se quiere pero no de que haga (además) otras cosas menos aceptables. Al realizar pruebas funcionales lo que se pretende es ponerse en los pies del usuario, usar el sistema como él lo usaría, sin embargo el probador debe ir más allá que cualquier usuario, generalmente se requiere apoyo de los usuarios finales ya que ellos pueden aportar mucho en el desarrollo de casos de prueba complejos, enfocados básicamente al negocio, posibles particularidades que no se hayan contemplado adecuadamente en el diseño funcional.


Generalmente los usuarios realizan las pruebas con la idea de que todo debería funcionar, a diferencia del probador que tiene más bien una misión destructiva, su objetivo será encontrar alguna posible debilidad y si la llega a ubicar se esforzará porque deje de ser pequeña y posiblemente se convertirá en un gran error, cada error encontrado es un éxito.


Pruebas de Software

Las pruebas requieren que se descarten ideas preconcebidas sobre la corrección del software que se acaba de desarrollar y se supere cualquier conflicto de intereses que aparezcan cuando se descubran errores. Las pruebas de software son la actividad más común de control de calidad realizada en los proyectos de desarrollo o mantenimiento de aplicaciones y sistemas. Aunque un aseguramiento de calidad de software más eficaz debería incluir otras técnicas como por ejemplo, inspecciones y revisiones (automatizadas o no) de modelos y documentos no ejecutables de las primeras fases de desarrollo.

El software es refinado a través de iteraciones en el ciclo de vida. El ciclo de vida de prueba se beneficia siguiendo un proceso iterativo equivalente. En cada iteración el equipo de desarrollo produce uno o más builds, cada builds es un canidato importante a probar.

Los objetivos del equipo de desarrollo difieren de una iteración a otra. El equipo de prueba estructura su prueba de acuerdo a los objetivos de la iteración. En una iteración x, se puede implementar y ejecutar determinadas pruebas. Cualquiera de las pruebas desarrolladas en la iteración x son candidatas para pruebas x+1. Cuando hay pruebas que son repetibles varias veces se podrían automatizar para hacer así mas sencillo el proceso.

Las pruebas de software no garantizan que un software esté libre de errores, sino que se detecten la mayor cantidad de defectos posibles en el mismo para su debida corrección. Si al ejecutar las pruebas no se encuentran errores esto indica que las pruebas realizadas no fueron lo suficientemente eficientes.

Como objetivos principales de las pruebas de software debemos tener presentes:
  • Planificar las pruebas necesarias en cada iteración.
  • Diseñar e implementar las pruebas creando los casos de pruebas que especifiquen los mismo qué probar.
  • Realizar diferentes tipos de pruebas y manejar los resultados de cada prueba sistemáticamente. Las construcciones en las que se detecten defectos serán probadas nuevamente hasta tanto esten libres de errores.
Las pruebas de software se llevan a cabo para brindar un mayor nivel de confiabilidad en los productos que se generan, detectar fallas o errores y aumentar la calidad del producto final.

Existen 4 niveles de pruebas:

-Unidad

-Integración

-Sistema

-Aceptación

En el nivel de Unidad se encuentras las pruebas unitarias como su nombre lo indica. En el encontramos las Pruebas de Caja Blanca las cuales van dirigidas a probar el código de módulos independientes y también están las Pruebas de Caja Negra las cuales probarán las funcionalidades específicas de cada módulo por separado.

En el nivel de Integración están las Pruebas de Integración como su nombre lo indica, las mismas son las encargadas de probar las funcionalidades dependientes entre módulos, probando así la integración de los módulos involucrados.

En el nivel de Sistema se encuentran la mayor cantidad de tipos de pruebas. En este nivel se prueba el sistema como un todo en conjunto. Aquí encontramos las pruebas funcionales las cuales probarán el funcionamiento básico de cada funcionalidad. También tenemos las pruebas de Carga la cual se utiliza para enviar datos al sistema para ver hasta que punto admite capacidad de volumen de información. También tenemos las pruebas de Estrés, estas tienen como objetivo hacer colapsar al sistema en cuanto a la mayor cantidad de peticiones de usuarios a una misma funcionalidad o valor como resultado de alguna consulta realizada. También están en este nivel los Test de Penetración los cuales tienen como objetivo violar todas las políticas de seguridad del sistema, tanto como agente externo como interno.

En el nivel de Aceptación tenemos las pruebas de Aceptación como su nombre lo indica, las mismas son realizadas por el usuario final o cliente. Se llevan a cabo en dos ambientes, el primero es un ambiente creado por el equipo de desarrollo el cual estará enmarcado a lo que realmente quiere el equipo de desarrollo que sea probado. El otro ambiente ya es preparado por el usuario final o cliente, ambiente el cual estará lejos del equipo de desarrollo.

Nota Importante: Existen también las Pruebas de Regresión, las cuales se realizan para corregir errores que antes no existían debido a la incorporación de nuevas funcionalidades. Estas pruebas están presentes en todo el proceso de pruebas.


Controlar la Calidad del Software

Para controlar la calidad del software es necesario ante todo, definir los parámetros, indicadores o criterios de medición.

El control de la calidad consiste en una serie de inspecciones, revisiones y pruebas utilizadas a lo largo del proceso del software para asegurar que cada producto cumple con los requisitos pactados por ambas partes. El control de la calidad incluye un bucle de realimentación (feedback) del proceso que creó el producto. La combinación de medición y realimentación permite afinar el proceso cuando los productos de trabajo creados fallan al cumplir sus especificaciones. Este enfoque ve el control de la calidad como parte del proceso de fabricación.

Existen muchas maneras de llevar a cabo el control de la calidad, las actividades de control pueden ser manuales, completamente automáticas o una combinación de ambas. Lo que si no puede faltar en el control de la calidad es la definición de todos los productos así como las especificaciones de los mismos, en las que se puedan comparar los resultados de cada proceso. El bucle de realimentación es esencial para reducir los defectos producidos.

Controlar la calidad es mantener una observación constante en el cumplimiento de las tareas que pueden ofrecer una calidad objetiva a la forma en cómo se está desarrollando un proyecto. Permite realizar las rectificaciones pertinentes al desarrollo en cuanto este empieza a desviarse de sus objetivos, alejando la inclusión de la calidad al trabajo. Esto permite realizar el mejoramiento de los procesos débiles, lo que definitivamente desembocará en un aseguramiento de la calidad en los procesos ejecutados por la organización.

No es posible desarrollar un software sin antes haber creado una unidad organizativa que guie el proceso, que sea la encargada de definir y planificar las actividades y procesos. Sin embargo todos estos mecanismos por si solos no garantizan que se cumplan todas las orientaciones al pie de la letra, para ellos es imprescindible implantar todos los mecanismos de control que sean necesarios.