Está en la página 1de 8

Resumen sobre Testing

I Es el proceso de ejecutar un producto para ...


I Verificar que satisface los requerimientos (en nuestro caso, la
especificación)
I Identificar diferencias entre el comportamiento real y el
comportamiento esperado (IEEE Standard for Software Test
Documentation, 1983).

I Objetivo: encontrar defectos en el software.

I Representa entre el 30 % al 50 % del costo de un software


confiable.

Input

Comportamiento
Comportamiento
esperado del
obtenido del
progama
progama
(ORÁCULO)
¿Obtenido = Esperado?

Distinto Igual

Falla OK

Definiciones
Test Input, Test Case y Test Suite

I Programa bajo test: Es el programa que queremos saber si


funciona bien o no.
I Test Input (o dato de prueba): Es una asignación concreta de
valores a los parámetros de entrada para ejecutar el programa
bajo test.
I Test Case: Caso de Test (o caso de prueba). Es un programa
que ejecuta el programa bajo test usando un dato de test, y
chequea (automáticamente) si se cumple la condición de
aceptación sobre la salida del programa bajo test.
I Test Suite: Es un conjunto de casos de Test (o de conjunto
de casos de prueba).

Hagamos Testing
I ¿Cuál es el programa bajo test?
I Es la implementación de una especificación.
I ¿Entre qué datos de prueba puedo elegir?
I Aquellos que cumplen la precondición en la especificación
I ¿Qué condición de aceptación tengo que chequear?
I La condición que me indica la postcondición en la
especificación.
I ¿Qué pasa si el dato de prueba no satisface la precondición de
la especificación?
I Entonces no tenemos ninguna condición de aceptación
Limitaciones del testing
I Al no ser exhaustivo, el testing NO puede probar (demostrar)
que el software funciona correctamente.

“El testing puede demostrar la presencia de


errores nunca su ausencia” (Dijkstra)

I Una de las mayores dificultades es encontrar un conjunto de


tests adecuado:
I Suficientemente grande para abarcar el dominio y maximizar
la probabilidad de encontrar errores.
I Suficientemente pequeño para poder ejecutar el proceso con
cada elemento del conjunto y minimizar el costo del testing.

Retomando... ¿Qué casos de test elegir?


1. No hay un algoritmo que proponga casos tales que encuentren
todos los errores en cualquier programa.
2. Ninguna técnica puede ser efectiva para detectar todos los
errores en un programa arbitrario
3. En ese contexto, veremos dos tipos de criterios para
seleccionar datos de test:
I Test de Caja Negra: los casos de test se generan analizando
la especificación sin considerar la implementación.
I Test de Caja Blanca: los casos de test se generan analizando
la implementación para determinar los casos de test.

Criterios de caja negra o funcionales


I Los datos de test se derivan a partir de la descripción del
programa sin conocer su implementación.

proc fastexp(in x : Z, in y : Z, out result : Z ){


Pre {(x 6= 0 ∨ y 6= 0) ∧ (y ≥ 0)}
Post {result = x y )}
}

Criterios de caja blanca o estructurales


I Los datos de test se derivan a partir de la estructura interna
del programa.

int fastexp ( int x , int y) {


int z = 1;
while( y != 0 ) {
i f (impar(y)) then {
z = z ∗ x;
y = y − 1;
}
x = x ∗ x;
y = y / 2;
}
return z ; ¿Qué pasa si y es potencia de 2?
} ¿Qué pasa si y = 2n − 1?
Control-Flow Graph

I El control flow graph (CFG) de un


programa es sólo una
representación gráfica del
programa.
I El CFG es independiente de las
entradas (su definición es estática)
I Se usa (entre otras cosas) para
definir criterios de adecuación para
test suites.
I Cuanto más partes son ejercitadas
(cubiertas), mayores las chances de
un test de descubrir una falla
I partes pueden ser: nodos, arcos,
caminos, decisiones...

if (COND) while (COND) for (INIT, ...

ThenBlock ElseBlock BLOCK COND

BLOCK
if (COND)
ThenBlock while (COND)
BLOCK INCR
else
ElseBlock

for (INIT; COND; INCR)


BLOCK

Ejemplo #1: valorAbsoluto int res = 0; Ejemplo #2: Sumar int i = 1;


Control Flow Graph Control Flow Graph
int suma = 0;
int valorAbsoluto ( int n) { int sumar( int n) {
if( n > 0 ) int i = 1;
int res = 0; while( i <= n )
if( n > 0 ) { int suma = 0;
res = n; True False True
} else { while( i <= n ) { suma = suma + i;
res = n; res = -n; suma = suma + i;
res = -n;
} i = i + 1;
i = i + 1; False
return res; }
} return res; return suma;
return suma;
}

Ejemplo #3: crearVectorN vector<int> v; Ejemplo #4: valorAbsoluto


Control Flow Graph Control Flow Graph
vector<int> crearVectorN(int n) { for (int i=0;...;...)
int valorAbsoluto ( int n) {
int res = n;
vector<int> v;
int res = n;
for (int i=0; i<n; i=i+1) {
v.push back(0);
for (...; i<n; ...) if( n < 0 ) {
} res = -n; if( n < 0 )
True
return v; }
} v.push back(0); return res; True
}
res = -n; False
for (...;...; i=i+1); False

return v; return res;


Criterios de Adecuación
I ¿Cómo sabemos que un test suite es suficientemente bueno?
I Un criterio de adecuación de test es un predicado que toma un valor de verdad para una tupla <programa, test suite>
I Usualmente expresado en forma de una regla del estilo: todas las sentencias deben ser ejecutadas

Cubrimiento de Sentencias
I Criterio de Adecuación: cada nodo (sentencia) en el CFG debe ser ejecutado al menos una vez por algún test case
I Idea: un defecto en una sentencia sólo puede ser revelado ejecutando el defecto
I Cobertura:
cantidad nodos ejercitados
cantidad nodos

vector<int> v;

for (int i=0;...;...)


Un NODO (o SENTENCIA) es cada globito
de mi Control-Flow Graph.
for (...; i<n; ...)
Los marco en rojo en el CFG a la izquierda.
True
v.push back(0);

for (...;...; i=i+1); False

return v;

Cubrimiento de Arcos
I Criterio de Adecuación: todo arco en el CFG debe ser ejecutado al menos una vez por algun test case
I Si recorremos todos los arcos, entonces recorremos todos los
nodos. Por lo tanto, el cubrimiento de arcos incluye al cubrimiento de sentencias.
I Cobertura:
cantidad arcos ejercitados
cantidad arcos

I El cubrimiento de sentencias (nodos) no incluye al cubrimiento de arcos. ¿Por qué?

int res = n;
Un ARCO es cada una de las flechitas de
un Control-Flow Graph.
if( n < 0 ) Los marco en AZUL en el CFG a la izquierda.
True

res = -n; False

return res;
Cubrimiento de Nodos no incluye cubrimiento de Arcos
Sea el siguiente CFG:

int res = n;

if( n < 0 )

True

res = -n; False

return res;

En este ejemplo, puedo construir un test suite que cubra todos los nodos pero que no cubra todos los arcos.
Muestro como puedo cubrir todos los nodos pero no todos los arcos en verde

Me queda el arco correspondiente a FALSE sin cubrir, aun asi, cubri todos los nodos

Cubrimiento de Decisiones (o Branches)


I Criterio de Adecuación: cada decisión (arco True o arco False) en el CFG debe ser ejecutado
I Por cada arco True o arco False, debe haber al menos un test case que lo ejercite.
I Cobertura:
cantidad decisiones ejercitadas
cantidad decisiones
I El cubrimiento de decisiones no implica el cubrimiento de los arcos del CFG. ¿Por qué?

int res = n;
Una DECISION o BRANCHE es cada arco TRUE o FALSE
que aparece en un Control-Flow Graph.
if( n < 0 ) Los marco en MAGENTA en mi CFG a la izquierda

True

res = -n; False

return res;

Cubrimiento de Branches no incluye cubrimiento de Arcos


Sea el siguiente CFG:

int res = 0; Suponiendo que tengo un test Suite con dos


Test Cases (AZUL y ROJO), muestro como puedo
if( n > 0 ) cubrir todos los BRANCHES (True o False),
True False pero no todos los arcos pues el programa se indefine
antes de llegar al ultimo arco
res = n; res = -n;

cout << 1/0;

return res;

En este ejemplo, puedo construir un test suite que cubra todos los branches pero que no cubra todos los arcos.
CFG de crearVectorN
vector<int> v;

for (int i=0;...;...)

for (...; i<n; ...)


True
v.push back(0);

for (...;...; i=i+1); False

return v;

I ¿Cuántos nodos (sentencias) hay? 6


I ¿Cuántos arcos (flechas) hay? 6
I ¿Cuántas decisiones (arcos True y arcos False) hay? 2

Otros Criterios de Adecuacion para nuestros Test Suite

Cubrimiento de Condiciones Básicas


I Una condición básica es una fórmula atómica (i.e. no
divisible) que componen una decisión.
I Ejemplo: (digitHigh==1 || digitLow==-1) && len>0
I Condiciones básicas:
I digitHigh==1
I digitLow==-1
I len>0
I No es condición básica: (digitHigh==1 || digitLow==-1) Pues puede ser dividida en digitHigh==1 y digitLow==-1

I Criterio de Adecuación: cada condición básica de cada decisión en el CFG debe ser evaluada a verdadero y a falso al
menos una vez
I Cobertura: Cubrimiento de Condiciones Básicas
cantidad de valores evaluados en cada condicion
2 ∗ cantidad condiciones basicas

Cubrimiento de Condiciones Básicas


En el siguiente test suite:
I Sea una única decisión:
Entrada digitHigh==1? digitLow==-1? len>0?
(digitHigh==1 || digitLow==-1) && len>0
digitHigh=1,
I Y el siguiente test case: digitLow=0 True False True
Entrada digitHigh==1? digitLow==-1? len>0? len=1,
digitHigh=1, digitHigh=0,
digitLow=0 True False True digitLow=-1 False True False
len=1, len=0,
I ¿Cuál es el cubrimiento de condiciones básicas?
¿Cuál es el cubrimiento de condiciones básicas?
3 3 6 6
Ccond.básicas = = = 50 % Ccond.básicas = = = 100 %
2∗3 6 2∗3 6
Pues evalue digitHigh==1 en T rue
digitLow ==-1 en False
len > 0 en T rue

me faltaría evaluar a las que evalue en T rue en False y a la


de False en T rue para obtener 100% de cobertura de
Condiciones Basicas
Cubrimiento de Branches y Condiciones Básicas
I Observación Branch coverage no implica cubrimiento de Condiciones Basicas
I ´
Ejemplo: if(a && b)
I Un test suite que ejercita solo a = true, b = true y a = false, b = true logra cubrir ambos branches de if(a && b)
I Pero: no alcanza cubrimiento de decisiones básica ya que falta b = false

I El criterio de cubrimiento de Branches y condiciones básicas


necesita 100 % de cobertura de branches y 100 % de cobertura de condiciones básicas

I Para ser aprobado, todo software que controla un avión


necesita ser testeado con cubrimiento de branches y
condiciones básicas (RTCA/DO-178B en EEUU y EUROCAE
ED-12B en UE).

Cubrimiento de Caminos
I Criterio de Adecuación: cada camino en el CFG debe ser transitado por al menos un test case
I Cobertura:
cantidad caminos transitados
cantidad total de caminos

Caminos para el CFG de valorAbsoluto


Sea el siguiente CFG:

int res = n;

if( n < 0 )

True

res = -n; False

return res;

¿Cuántos caminos hay en este CFG? 2 . Los marco en ROJO y AZUL

Caminos para el CFG de sumar


int i = 1;

int suma = 0;

while( i <= n )
True
suma = suma + i;

i = i + 1; False

return suma;

¿Cuántos caminos hay en este CFG?


La cantidad de caminos no está acotada (∞) . Marco algunos con diferentes colores.

Como no esta acotada la cantidad de caminos, esto hace que quiza el cubrimiento de caminos no sea
algo práctico de usar, pues nunca podremos recorrer todos los caminos posibles de nuestro programa
Resumen: Criterios de Adecuacion Estructurales
I En todos estos criterios se usa el CFG para obtener una
métrica del test suite
I Sentencias: cubrir todas los nodos del CFG
I Arcos: cubrir todos los arcos del CFG
I Decisiones (Branches): Por cada if, while, for, etc., la
guarda fue evaluada a verdadero y a falso.
I Condiciones Básicas: Por cada componente básico de una
guarda, este fue evaluado a verdadero y a falso.
I Caminos: cubrir todos los caminos del CFG. Como no está
acotado o es muy grande, se usa muy poco en la práctica.

También podría gustarte