Está en la página 1de 102

Pruebas de Sistemas de

Informacin
Universidad de Castilla-La Mancha
Departamento de Tecnologas y Sistemas de
Informacin
Programa Oficial de Postgrado en Tecnologas Informticas
Avanzadas

Macario Polo Usaola


Departamento de Tecnologas y Sistemas de Informacin
Paseo de la Universidad, 4
13071-Ciudad Real
macario.polo@uclm.es

ndice
Captulo 1. La importancia de las pruebas en el ciclo de vida ......................... 7
1. El proceso de pruebas en el ciclo de vida ................................................. 7
2. Las pruebas en algunas modelos..............................................................9
3. El MTPF (Minimal Test Practice Framework) .......................................9
4. El plan de pruebas .................................................................................. 12
5. Automatizacin de las pruebas .............................................................. 13
Captulo 2. Niveles de prueba ........................................................................ 19
1. Pruebas de caja negra ............................................................................. 19
2. Pruebas estructurales o de caja blanca ................................................. 20
3. Pruebas unitarias.................................................................................... 21
3.1.

Un modelo de proceso para pruebas unitarias ..........................22

4. Pruebas de integracin ...........................................................................23


5. Pruebas de sistema .................................................................................24
6. Ejercicios ................................................................................................24
Captulo 3. Pruebas de caja blanca ................................................................ 27
1. Medidas de la cobertura.......................................................................... 27
1.1.

Cobertura de sentencias ............................................................. 27

1.2.

Cobertura de decisiones, de ramas o de todos los arcos............ 27

1.3.

Cobertura de condiciones...........................................................28

1.4.

Cobertura

de

condiciones/decisiones

(Decision/Condition

coverage, o DCC) ..........................................................................................29


1.5.

Cobertura modificada de condiciones/decisiones (MC/DC). ...29

1.6.

Cobertura mltiple de condiciones (MCC) ................................29

1.7.

Cobertura de todos los usos (all-uses) .......................................29

1.8.

Cobertura de caminos ................................................................29

1.9.

Cobertura de funciones ..............................................................30

1.10.

Cobertura de llamadas ...............................................................30

1.11.

Cubrimiento de bucles ...............................................................30

1.12.

Cubrimiento de carrera ..............................................................30

1.13.

Cobertura de operadores relacionales .......................................30

1.14.

Cobertura de tablas ....................................................................30

1.15.

Cobertura basada en mutacin ..................................................30

2. La mutacin ............................................................................................32
3

2.1.

Algo de terminologa ..................................................................33

2.2.

La mutacin como criterio de cobertura....................................33

2.3.

Proceso de pruebas basado en mutacin ...................................34

2.4.

Operadores de mutacin ............................................................36

3. Ejercicios................................................................................................. 37
Captulo 4. Los valores interesantes ...........................................................39
1. Un estudio inicial del problema del tringulo........................................39
2. Concepto de valor interesante................................................................42
2.1.

Clases de equivalencia................................................................42

2.2.

Valores lmite..............................................................................43

2.3.

Fundamento matemtico ...........................................................43

3. Criterios de cobertura para valores........................................................44


3.1.

Cada uso (each-use, o 1-wise) ....................................................44

3.2.

pair-wise (o 2-wise) ...................................................................45

3.3.

t-wise .......................................................................................... 47

3.4.

N-wise......................................................................................... 47

4. Casos de prueba redundantes ................................................................ 47


4.1.

Reduccin del conjunto de casos basado en mutacin..............48

4.2.

Algoritmo HGS ........................................................................... 51

4.3.

Mejoras de Gupta ....................................................................... 51

4.4.

Algoritmo de Heimdahl y George ..............................................52

4.5.

Algoritmo de McMaster y Memon .............................................52

5. Ejercicios.................................................................................................52
Captulo 5. Estrategias de combinacin para la generacin de casos de
prueba...................................................................................................................53
1. Estrategias de generacin de casos de prueba .......................................53
2. Estrategias no deterministas..................................................................54
2.1.

AETG: Automatic efficient test generator..................................54

2.2.

Algoritmos Genticos .................................................................54

3. Estrategias deterministas .......................................................................58


3.1.

Each choice .................................................................................59

3.2.

Base choice .................................................................................59

3.3.

Partly pair-wise ..........................................................................59

3.4.

All combinations.........................................................................59
4

3.5.

Anti-random ...............................................................................59

4. Estrategias de generacin fuera de la clasificacin anterior ................ 60


4.1.

Bsqueda Tab ........................................................................... 61

4.2.

Generacin mediante algoritmos bacteriolgicos. ....................62

5. Ejercicios.................................................................................................63
Captulo 6. Pruebas de caja negra..................................................................65
1. Pruebas de componentes ........................................................................65
1.1.

Uso de BIT wrappers ..................................................................65

1.2.

Mutacin de interfaces ............................................................... 67

2. Pruebas de servicios web........................................................................68


2.1.

WSDL..........................................................................................69

2.2.

Escritura de un cliente que acceda a un servicio web................70

2.3.

Pruebas de servicios web mediante perturbacin de datos....... 71

3. Pruebas de integracin con mquinas de estado en orientacin a


objetos............................................................................................................... 72
4. Ejercicios................................................................................................. 74
Captulo 7. Pruebas de artefactos diversos .................................................... 75
1. Testing basado en requisitos .................................................................. 75
2. Secuencias de mtodos...........................................................................78
3. Especificaciones formales o semiformales............................................. 79
3.1.

Propuesta de Tse y Xu ................................................................ 79

3.2.

Mtodo ASTOOT ........................................................................82

3.3.

Obtencin automtica de especificaciones algebraicas .............84

4. Pruebas a partir de mquinas de estado ................................................86


4.1.

Cobertura de transiciones ..........................................................86

4.2.

Cobertura de predicados ............................................................86

4.3.

Cobertura de pares de transiciones............................................87

4.4.

Cobertura de secuencia completa ............................................. 88

5. Obtencin de casos de prueba a partir de casos de uso .........................89


6. Diseo de clases orientados a la facilidad de pruebas .......................... 90
7. Criterios de cobertura de pruebas para diseos UML ...........................93
8. Revisiones e inspecciones de cdigo fuente...........................................94
9. Ejercicios ................................................................................................95
Captulo 8. Mtricas para el proceso de pruebas........................................... 97
5

1. Introduccin............................................................................................ 97
2. Porcentaje de deteccin de defectos.......................................................98
3. Porcentaje de defectos corregidos..........................................................98
4. Medida del retorno de la inversin (ROI)..............................................98
Captulo 9. Referencias ................................................................................ 101

Pruebas de sistemas de informacin

Captulo 1. LA IMPORTANCIA DE LAS PRUEBAS EN


EL CICLO DE VIDA

La fase de pruebas es una de las ms costosas del ciclo de vida software. En


sentido estricto, deben realizarse pruebas de todos los artefactos generados durante la construccin de un producto software, lo que incluye las especificaciones de requisitos, casos de uso, diagramas de diversos tipos y, por supuesto, el
cdigo fuente y el resto de elementos que forman parte de la aplicacin (como
por ejemplo, la base de datos). Obviamente, se aplican diferentes tcnicas de
prueba a cada tipo de producto software.
En este primer captulo se enmarca el proceso de pruebas dentro del ciclo de
vida software, se describe brevemente una serie de buenas prcticas para el proceso de pruebas, y se presentan algunos retos en cuanto a la automatizacin del
proceso.

1. El proceso de pruebas en el ciclo de vida


El estndar ISO/IEC 12207 [1] identifica tres grupos de procesos en el ciclo
de vida software:
-

Procesos principales, grupo en el que incluye los procesos de Adquisicin, Suministro, Desarrollo, Operacin y Mantenimiento.

Procesos de la organizacin, en donde se encuentran los procesos de


Gestin, Mejora, Infraestructura y Formacin.

Procesos de soporte o auxiliares, en donde estn los procesos de Documentacin, Gestin de la Configuracin, Auditora, Resolucin de
Problemas, Revisin Conjunta, Aseguramiento de la Calidad, Verificacin, Validacin,

No define, como vemos, un proceso de Pruebas como tal, sino que aconseja,
durante la ejecucin de los procesos principales o de la organizacin, utilizar los
procesos de soporte. Entre stos se encuentran los procesos de Validacin y de
Verificacin:

Pruebas de sistemas de informacin

El proceso de Validacin tiene como objetivo determinar si los requisitos y el sistema final cumplen los objetivos para los que se construy el
producto, respondiendo as a la pregunta el producto es correcto?

El proceso de Verificacin intenta determinar si los productos software


de una actividad se ajustan a los requisitos o a las condiciones impuestas en actividades anteriores. De este modo, la pregunta a la que responde este proceso es se est construyendo el producto correctamente?

Del proceso de Verificacin se observa la importancia de verificar cada uno


de los productos que se van construyendo, pues se asume que si lo que se va
construyendo es todo ello correcto, tambin lo ser el producto final. Igualmente, se observa que el proceso de Validacin resalta la importancia de comprobar
el cumplimiento de los objetivos de los requisitos y del sistema final, de suerte
que podra construirse un Plan de pruebas de aceptacin desde el momento
mismo de tener los requisitos, que sera comprobado al finalizar el proyecto. Si
tras la fase de requisitos viniese una segunda de diseo a alto nivel del sistema,
tambin podra prepararse un Plan de pruebas de integracin, que sera comprobado tras tener (o segn se van teniendo) codificados los diferentes mdulos
del sistema. Esta correspondencia entre fases del desarrollo y niveles de prueba
produce el llamado modelo en V, del que se muestra un ejemplo en la Figura 1.
En la figura se muestra cmo, efectivamente, mientras que en el desarrollo se va
de lo ms general a lo ms particular, en las pruebas se va de lo ms particular a
lo ms general: si lo primero que se hace es recolectar los requisitos con el usuario, las ltimas pruebas que se hacen son las de aceptacin, con el mismo usuario; si lo ltimo que se construye es el cdigo, lo primero que se hace son las
pruebas unitarias de dicho cdigo.

Pruebas de sistemas de informacin

Pruebas de
aceptacin

Requisitos

Pruebas de
sistema

Diseo de
alto nivel

Pruebas de
integracin

Diseo de
bajo nivel

Pruebas
unitarias

Cdigo

Figura 1. Modelo en V

2. Las pruebas en algunas modelos


El Capability Maturity Model (CMM) hace una consideracin especial de
las pruebas. Las reas de este modelo que ms relacionadas se encuentran con
la fase de pruebas son Software Product Engineering, Training Program,
Technology Change Management y Process Change Management. CMM establece cuatro niveles para la realizacin de pruebas: de unidad, de integracin, de
sistema y de aceptacin, adems de las de regresin, que se ejecutan para verificar la correccin de los cambios en el sistema. Deben redactarse un plan de
pruebas y definirse estndares de pruebas junto al resto del proceso. El grupo de
pruebas debe estar bien distinguido respecto del de desarrollo y debe realizar las
pruebas independientemente de ste.

3. El MTPF (Minimal Test Practice Framework)


Karlstrm et al. describen un proceso para pequeas organizaciones que deseen adoptar buenas prcticas en pruebas [2]. El MTPF (Minimal Test Practice
Framework) se estructura en cinco categoras y consta de tres fases (que,
aproximadamente, representan tres niveles de madurez). Su objetivo es pasar
de una estrategias de pruebas ad hoc a un proceso de pruebas claro y estructurado.

Pruebas de sistemas de informacin

A cada categora le corresponden un conjunto de prcticas de trabajo relacionadas con las pruebas, que deben realizarse segn la fase en la que se encuentre la organizacin. Las fases se describen en funcin de la cantidad de personal de desarrollo que trabaja en la organizacin. Para equipos de desarrollo
superiores a 30 personas, los propios autores recomiendan el uso de otros frameworks.
La Tabla 1 describe brevemente las actividades de cada fase y categora.

10

Pruebas de sistemas de informacin

Fase 3
(~30 personas)

Fase 2
(~20 personas)

Fase 1
(~10 personas)

Fases
Categoras

Mantenimiento del
sistema
Mantener el sistema para
que se adapte a la evolucin de la compaa

Creacin del sistema


Introduccin de sistema de
recogida y almacenamiento
de problemas de acuerdo a
estndares de Fase 1.
Definicin de procedimientos para recolectar, documentar, almacenar y reutilizar conocimiento de cada
proyecto.
Definicin de estndares de registro
Definicin de terminologa,
lenguaje, procedimientos,
etc.:
Campos que, juntos,
describan el problema
Que sigan el flujo del
tester
Fcil de entender
Que identifique cada
problema unvocamente
Que permita agrupar
problemas
Registro sistemtico de
defectos

Definicin de equipos
Creacin de un equipo de
pruebas independiente del
de desarrollo.
Los miembros de este
equipo pueden especializarse (usabilidad, seguridad, etc.).
Definicin de roles
Asignar los roles de responsable de pruebas y de
ingenieros de pruebas
(testers).
Las responsabilidades de
los testers son: gestin de
walkthroughs, gestin de,
desarrollo de casos de
prueba; gestin del sistema
de recogida de problemas;
gestin de experiencia.
Definir responsabilidades
Las responsabilidades son:
desarrollo de planes de
pruebas para cada proyecto; gestin del entorno de
pruebas; gestin del sistema de recogida de problemas; actualizacin de checklists; evaluacin de prcticas; control de necesidades
para la siguiente fase

Definicin de roles y organizacin

Inspecciones
Sustitucin progresiva los
walkthroughs por inspecciones que, al requerir
preparacin previa, resultan ms eficientes.
Se definirn los roles de
cada inspector.
Walkthroughs
Realizacin de walkthroughs antes de que el
software est preparado
para su ejecucin, idealmente en la fase de diseo.
El equipo de walkthroughs
se compone de desarrolladores y diseadores, al que
puede asistir un tester.
Uso de checklists
Creacin de checklists, o
revisin de las que pudieran estar siendo utilizadas.

Verificacin y validacin

Tabla 1. Resumen del MTPF

11

Gestin de riesgos
Se crear y mantendr una
base de datos de problemas
y experiencias que ayude a
predecir las reas de mayor
riesgo de los proyectos
antes de que acontezcan.
Casos de prueba
Se construyen casos de
prueba para comprobar
que se prueban las situaciones y acciones ms comunes. A la creacin de
casos de prueba se le asignarn varios testers, ya que
es una de las actividades
que requiere ms tiempo.
Se crearn varios casos
para cada escenario.
Gestin bsica
El entorno de pruebas debe
estar disponible siempre
que se requiera. Las actividades bsicas son: organizar el entorno de pruebas
para cada proyecto, mantenerlo actualizado y documentar su forma de uso.

Gestin de las pruebas

Coordinacin del aseguramiento de la calidad


Establecimiento de rutinas de
aseguramiento de la calidad,
de forma que se asegure que el
software no ser entregado
antes de que alcance el nivel
mnimo predeterminado.

Plan de pruebas
El plan de pruebas permite
recoger en un solo documento
todo lo relacionado con las
pruebas de cada proyecto
(p.ej., el IEEE Std. for Soft.
Test Documentation).
Es importante indicar los
diferentes hitos en el plan de
pruebas.

Planificacin

Pruebas de sistemas de informacin

Cada fase se introduce en la organizacin cuidadosamente, siguiendo cinco


pasos: preparar la fase, introducirla, revisarla, realizarla y evaluarla, como se
ilustra en la

n=1

Preparar
prcticas de la
fase n

Revisar
prcticas de la
fase n

Introducir
prcticas de la
fase n

Ejecutar
prcticas de la
fase n

[no]
[s]
Cambiar?

n++

Evaluar
prcticas de la
fase n

Figura 2. Mtodo seguido para introducir cada fase

4. El plan de pruebas
El plan de pruebas es un documento que se utiliza para indicar los recursos,
los elementos que se van a probar, las actividades, el personal y los riesgos asociados. El estndar IEEE 829 es el estndar para documentacin de las pruebas,
e indica la siguiente estructura para el plan de pruebas:
1) Identificador del documento.
2) Introduccin, resumen de los elementos y las caractersticas que se van a
probar.
3) Elementos que se van a probar (programas, mdulos)
4) Caractersticas que se van a probar.
5) Caractersticas que no se van a probar.
6) Enfoque general de la prueba.
7) Criterios de paso o fallo.
8) Criterios de suspensin y de reanudacin.
9) Documentacin asociada.
10) Actividades de preparacin y ejecucin de pruebas.
11) Entorno necesario.
12) Responsables.

12

Pruebas de sistemas de informacin

13) Necesidades de personal y de formacin.


14) Esquema de tiempos.
15) Riesgos asumidos y planes de contingencia.
16) Aprobaciones, con las firmas de los responsables.

5. Automatizacin de las pruebas


Diversos estudios recientes han destacado la falta de automatizacin de las
tareas relacionadas con las pruebas de software en la mayora de las compaas
[3, 4]. De acuerdo con Meudec [5], hay tres lneas de automatizacin en este
contexto:
1)

Tareas administrativas, como el registro de especificaciones o la


generacin de informes.

2)

Tareas mecnicas, como la ejecucin y la monitorizacin, o las posibilidades de captura y reejecucin de casos.

3)

Tareas de generacin de casos de prueba. Respecto estas tareas, [6] indican tres enfoques:
a. Generar casos de prueba a partir de cdigo fuente para alcanzar
un nivel determinado de cobertura.
b. Dado el conocimiento del ingeniero de pruebas sobre el programa
y sobre su comportamiento esperado, generar automticamente
entradas y comprobar las salidas.
c. Dada una especificacin formal, generar automticamente casos
de prueba para una implementacin de esa especificacin.

En los ltimos aos se han desarrollado una serie de herramientas ligadas al


Test Driven Development (Desarrollo Dirigido por las Pruebas) que han tenido
un xito importante en el desarrollo de software. Estas herramientas, que se
agrupan habitualmente bajo la denominacin X-Unit, automatizan parcialmente las pruebas unitarias de cdigo orientado a objetos, en los que habitualmente
se considera que la unidad de pruebas es la clase. En X-Unit, siendo K la clase
que se va a probar (abreviadamente CUT, de las siglas Class Under Test), se
construye una clase TestK que contiene mtodos (que realmente constituyen

13

Pruebas de sistemas de informacin

casos de prueba) que ejercitan las diversas funcionalidades ofrecidas por K. As,
cada caso de prueba suele consistir en la construccin de una instancia de la
CUT, en la ejecucin de una serie de servicios sobre sta y en la comprobacin
del resultado (a lo que se le llama orculo). La Tabla 2 muestra la clase Java TestAccount, que prueba la clase de dominio Account (que representa una cuenta
bancaria) mediante tres casos de prueba, correspondientes los tres mtodos
test1, test2 y test3.

test1 construye una instancia de la CUT, ingresa 1000 euros en ella y, a


continuacin, comprueba en su orculo que el saldo de la cuenta es, en
efecto, de 1000 euros.

test2 crea una instancia de la CUT, ingresa 300 euros y retira 1000.
Puesto que la cuenta no tiene saldo suficiente, se espera que la CUT
lance una excepcin de saldo insuficiente (que se captura en el bloque
catch), superndose en este supuesto el caso de prueba. Si la excepcin
no se lanza, el control del programa no salta al catch y se ejecutara la
instruccin fail, que indica al entorno de pruebas que el caso no ha sido
superado.

test3 crea una instancia de la CUT, ingresa 1000 euros y luego comprueba que el saldo es de 1000 euros; despus retira 300 y comprueba
que el saldo es de 700 euros. Si se produce alguna excepcin, se salta al
bloque catch, que ejecuta el fail, indicando al entorno de pruebas que el
caso de prueba ha fallado.

Una importante ventaja de los entornos X-Unit es que los casos de prueba se
guardan en ficheros separados, lo que permite reejecutarlos segn la CUT va
siendo modificada (lo que los convierte en casos vlidos para pruebas de regresin). Una desventaja es que se requiere un esfuerzo importante para escribir
buenos casos de prueba que consigan probar todo el funcionamiento de la CUT.
Por otro lado, estos entornos no generan normalmente demasiados resultados
cuantitativos sobre los resultados de las pruebas, informando la mayora de
ellos de si los casos han encontrado o no defectos en la CUT.

14

Pruebas de sistemas de informacin

package samples.results;
import junit.framework.*;
import samples.Account;
import samples.InsufficientBalanceException;
public class TestAccount extends TestCase {
public void test1() {
Account o=new Account();
o.deposit(1000);
assertTrue(o.getBalance()==1000);
}
public void test2() {
try {
Account o=new Account();
o.deposit(300);
o.withdraw(1000);
fail("InsufficientBalanceException expected");
}
catch (InsufficientBalanceException e) {
}
}
public void test3() {
try {
Account o=new Account();
o.deposit(1000);
assertTrue(o.getBalance()==1000);
o.withdraw(300);
assertTrue(o.getBalance()==700);
}
catch (Exception e) {
fail("Unexpected exception");
}
}
public static void main (String [] args) {
junit.swingui.TestRunner.run(TestAccount.class);
}
}

Tabla 2. Tres casos de prueba de JUnit para una clase Account (Cuenta
bancaria)

La Tabla 3 ofrece una valoracin aproximada del grado de automatizacin


que los entornos X-Unit consiguen hacer respecto de la automatizacin de las
pruebas, de acuerdo con las tres lneas mencionadas ms arriba.
Generacin de casos
Tareas mecniEjecucin y monitorizacin
cas
Reejecucin
Tareas adminis- Registro de especificaciones
trativas
Generacin de informes

5%
100%
100%
80%
10%

Tabla 3. Automatizacin de las pruebas conseguida por los entornos XUnit

15

Pruebas de sistemas de informacin

As pues, queda bastante por hacer en cuanto a automatizacin de las pruebas. En muchas ocasiones, lo que falta es una cultura de pruebas en las propias
empresas. Rice enumera y explica los diez principales obstculos que existen en
las empresas respecto de la automatizacin del proceso de pruebas:

Falta de herramientas, debida fundamentalmente a su elevado precio o a que las existentes no se ajusten al propsito o entorno para el
que se necesitan. La primera razn parece deberse a la no mucha importancia que habitualmente se le da a la fase de pruebas, y eso que el
costo de corregir un error puede, en muchos casos, superar al de la licencia de uso. Sera conveniente evaluar el coste de correccin de defectos del software entregado y compararlo con el de la licencia de la
herramienta de pruebas.

Falta de compatibilidad e interoperabilidad entre herramientas.

Falta de proceso de gestin de la configuracin. Igual que las diferentes versiones del cdigo fuente, las pruebas, especialmente las de
regresin, deben someterse a un control de versiones. Recurdese que
el proceso de Gestin de la Configuracin es uno de los procesos de soporte del estndar ISO/IEC 12207 , que debera utilizarse en la ejecucin de los procesos principales, y muy especialmente en los de Desarrollo y Mantenimiento.

Falta de un proceso bsico de pruebas y de conocimiento de qu


es lo que se debe probar.

Falta de uso de las herramientas de prueba que ya se poseen,


bien por su dificultad de uso, por falta de tiempo para aprender a manejarla, por falta de soporte tcnico, obsolescencia, etc.

Formacin inadecuada en el uso de la herramienta.

La herramienta no cubre todos los tipos de prueba que se desean (correccin, fiabilidad, seguridad, rendimiento, etc.). Obviamente, a la hora de elegir la herramienta, deberan tenerse priorizados los
tipos de pruebas, y entonces hacer la eleccin de la herramienta basados en esto. A veces tambin es necesario utilizar no una, sino varias

16

Pruebas de sistemas de informacin

herramientas de prueba, as como tener en cuenta que es imposible automatizar el 100% de las pruebas.

Falta de soporte o comprensin por parte de los gestores, debido otra vez a la escasa importancia que habitualmente se le da a la fase de pruebas.

Organizacin inadecuada del equipo de pruebas.

Adquisicin de una herramienta inadecuada.

17

Pruebas de sistemas de informacin

Captulo 2. NIVELES DE PRUEBA


Tradicionalmente, se distinguen dos tipos bsicos de pruebas: pruebas de
caja blanca y pruebas de caja negra que, adems, suelen subdividirse en niveles
aun ms especficos. As, las pruebas de caja blanca se aplican, normalmente, a
pruebas unitarias y a ciertas pruebas de integracin, mientras que las de caja
negra hacen referencia, en general, tanto a pruebas unitarias, como funcionales,
de integracin, de sistema e, incluso, de aceptacin.
En este captulo se presenta una breve introduccin a las pruebas de caja
blanca y negra, y se describen algunas caractersticas de los niveles de prueba.

1. Pruebas de caja negra


En este tipo de pruebas, el elemento que se va a probar se entiende como
una caja negra de la que slo se conocen sus entradas y sus salidas. As, al elemento bajo prueba se lo somete a una serie de datos de entrada, se observan las
salidas que produce y se determina si stas son conformes a la entradas introducidas.
Un conocido problema que se utiliza con frecuencia en el contexto de las
pruebas de software es el de la determinacin del tipo de un tringulo, que fue
originalmente propuesto por Bertrand Myers [7]: adaptado a la orientacin a
objetos, se trata de probar una clase que dispone de una operacin que calcula el
tipo de un tringulo segn las longitudes de los lados. Esta operacin devuelve
un entero que representa si el tringulo es equiltero, issceles, escaleno si no es
un tringulo (porque tenga lados de longitud cero o negativa, o porque la suma
de dos lados sea menor o igual a la suma del tercero). En la Figura 3 se muestra
la estructura de la clase Tringulo, que consta de un constructor, tres operaciones set que asignan una longitud a los lados del tringulo y un mtodo getTipo,
que devuelve un entero que representa el tipo del tringulo.
Bajo un enfoque de caja negra, el punto de vista que interesa al ingeniero de
software se ilustra en las cuatro imgenes de la Figura 3, en las que se pasan
diferentes ternas de valores a los mtodos que asignan la longitud a los lados del

19

Pruebas de sistemas de informacin

tringulo (setI, setJ, setK) y luego se comprueba nicamente si el resultado devuelto por getTipo es el correcto.

Figura 3. El problema del tringulo, bajo un enfoque de caja negra

Como puede comprobarse, si los casos de prueba de caja negra se superan,


el ingeniero de pruebas estar seguro de que la CUT se comporta correctamente
para los datos de prueba utilizados en esos casos de prueba: en el caso del tringulo issceles, por ejemplo, en la figura se comprueba que un tringulo con longitudes 2, 2 y 3 es issceles; ahora bien, la implementacin de la clase determinar tambin que el tringulo es issceles para lados de longitudes 2, 3 y 2?
Con el fin de alcanzar una mayor seguridad respecto del comportamiento
correcto de la CUT se introduce la idea de las pruebas estructurales o de caja
blanca.

2. Pruebas estructurales o de caja blanca


Las pruebas de caja blanca realizan, de alguna manera, un seguimiento del
cdigo fuente segn se van ejecutando los casos de prueba, de manera que se
determinan de manera concreta las instrucciones, bloques, etc. que han sido
ejecutados por los casos de prueba. As pues, mediante este tipo de pruebas se
puede saber cunto cdigo se ha recorrido.
As, en el mismo problema del tringulo que comentbamos antes, el ingeniero de pruebas se fijar ahora en el cdigo que implementa su funcionalidad y
observar, para cada terna de entradas x1, x2, etc., el recorrido seguido por los
casos de prueba en la implementacin de la clase (Figura 4).
20

Pruebas de sistemas de informacin

Figura 4. El problema del tringulo, desde un punto de vista de caja


blanca

As, dependiendo de las ramas o caminos o nodos visitados por los casos de
prueba, el ingeniero estar ms o menos seguro de la buena, muy buena o mediana calidad del software objeto de estudio. Existen formas muy variadas de
medir esa cantidad de cdigo recorrido mediante lo que se llaman criterios de
cobertura.
Para Cornett [8], el anlisis de cobertura del cdigo es el proceso de:
-

Encontrar fragmentos del programa que no son ejecutados por los casos de prueba.

Crear casos de prueba adicionales que incrementen la cobertura.

Determinar un valor cuantitativo de la cobertura (que es, de manera


indirecta, una medida de la calidad del programa).

Adicionalmente, el anlisis de cobertura tambin permite la identificacin


de casos de prueba redundantes, que no incrementan la cobertura.

3. Pruebas unitarias
Las pruebas unitarias centran su aplicacin en lo que se denomina la unidad de prueba que, dependiendo del contexto, puede ser una clase, un mtodo
o un subsistema. El estndar ANSI/IEEE 1008/1987, define la unidad de prueba de la siguiente forma [9]:
Un conjunto de uno o ms mdulos de un programa, junto a con los datos de
control asociados (por ejemplo, tablas), procedimientos de uso y procedimientos de operacin que satisfagan las siguientes condiciones:
(1) Todos los mdulos pertenecen a un nico programa
(2) Al menos uno de los mdulos nuevos o cambiados del conjunto no ha pasado las pruebas unitarias (puesto que una unidad de prueba puede contener uno o ms mdulos previamente probados)

21

Pruebas de sistemas de informacin

(3) El conjunto de mdulos junto con sus datos y procedimientos asociados


son el nico objetivo del proceso de pruebas

En general, en orientacin a objetos se asume que la unidad de prueba es la


clase, por lo que se comprueba que el estado en el que queda la instancia de la
clase que se est probando1 es correcto para los datos que se le pasan como entrada. As, las pruebas unitarias de caja negra entienden la clase como, en efecto, una caja cuyo interior no interesa: lo nico que importa desde este punto de
vista es el conjunto de entradas suministradas y las salidas obtenidas.
3.1.

Un modelo de proceso para pruebas unitarias

Las pruebas de caja negra y de caja blanca no son excluyentes, sino que son
complementarias: con las de pruebas de caja negra se buscan errores en la CUT,
y con las de caja blanca nos aseguramos de que todo el cdigo (segn el criterio
de cobertura que se haya seleccionado) ha sido recorrido.
As, un proceso de pruebas unitarias que combine tcnicas de caja negra con
tcnicas de caja blanca seguir los siguientes pasos:
1) Sea C la CUT
2) Escribir un conjunto de casos de prueba TC para probar C
3) Ejecutar TC sobre C con una herramienta de caja negra
4) Si TC descubre errores en C, entonces corregir C y volver al paso 3
5) Ejecutar TC sobre C con una herramienta de caja blanca
6) Si TC no alcanza un umbral de cobertura mnimo sobre C, entonces es
necesario escribir nuevos casos de prueba que se aaden a TC, y se vuelve al paso 3
7) Se est en este paso cuando TC no ha encontrado errores en C y cuando
TC ha recorrido todo el cdigo de C. En esta situacin, todo el cdigo ha
sido probado sin descubrir errores, con lo que la clase C tiene una calidad muy alta.
Este proceso se muestra grficamente en la Figura 5: obsrvese que, despus
de ejecutar las pruebas de caja blanca, el ingeniero de pruebas se pregunta si la
cobertura obtenida alcanza un determinado umbral, que deber haber sido

A la clase que se est probando se la llama en ingls class under test, y en muchos artculos

y papers se abrevia diciendo CUT.

22

Pruebas de sistemas de informacin

determinado con anterioridad al comienzo del proceso. Dependiendo del criterio de cobertura elegido, el umbral puede ser ms o menos exigente: as, matar
ms del 90% de los mutantes puede ser muy difcil para algunos problemas, por
lo que este valor sera un buen umbral al utilizar tcnicas de mutacin; para cobertura de sentencias, sin embargo, es necesario recorrer el 100% de ellas.
Seleccionar C (CUT)

Generar un conjunto de
casos TC para probar C

Caja negra:
buscar errores en C
usando TC

[se encuentran errores]


Corregir C
[no se encuentran errores]
[no se alcanza umbral]
Caja blanca:
medir cobertura de TC sobre C

Aadir casos a TC
[se alcanza umbral]

Figura 5. Estructura del proceso de pruebas unitarias, combinando


pruebas funcionales (caja negra) con estructurales (caja blanca)

4. Pruebas de integracin
Las pruebas de integracin se emplean para comprobar que las unidades de
prueba, que han superado sus pruebas de unidad, funcionan correctamente
cuando se integran, de manera que lo que se tiende a ir probando es la arquitectura software. Durante la integracin, las tcnicas que ms se utilizan son las de
caja negra, aunque se pueden llevar a cabo algunas pruebas de caja blanca para
asegurar que se cubren los principales flujos de comunicacin entre las unidades [10].

23

Pruebas de sistemas de informacin

En el contexto de la orientacin a objetos, las pruebas de integracin pretenden asegurar que los mensajes que fluyen desde los objetos de una clase o
componente se envan y reciben en el orden adecuado en el objeto receptor, as
como que producen en ste los cambios de estado que se esperaban [11].

5. Pruebas de sistema
Las pruebas de sistema tienen por objetivo comprobar que el sistema, que
ha superado las pruebas de integracin, se comporta correctamente con su entorno (otras mquinas, otro hardware, redes, fuentes reales de informacin,
etc.).
Bajo este nivel de pruebas encontramos varios subniveles [10]:
1) Pruebas de recuperacin. Consisten en forzar el fallo del software y comprobar que la recuperacin se lleva a cabo de manera correcta, devolviendo al
sistema a un estado coherente.
2) Pruebas de seguridad. Intentan verificar que los mecanismos de proteccin incorporados al sistema lo protegern, de hecho, de penetraciones inadecuadas.
3) Pruebas de resistencia. Estas pruebas estn diseadas para que el sistema
requiera recursos en cantidad, frecuencia o volumen anormales. La idea es intentar que el sistema se venga abajo por la excesiva tensin a la que se lo somete.
4) Pruebas de rendimiento. En sistemas de tiempo real o sistemas empotrados, es inaceptable que el software proporcione las funciones requeridas fuera
de las condiciones de rendimiento exigidas.

6. Ejercicios
1) Escriba una clase para calcular el valor medio de 3 nmeros que se pasan
como parmetros. A continuacin, someta el programa al proceso de pruebas
descrito en la Figura 5 hasta que:
(a) Se hayan recorrido todas las sentencias.
(b) Se hayan recorrido todas las condiciones a true y a false.
La interfaz de la clase debe ser la siguiente:

24

Pruebas de sistemas de informacin

Medio
+Medio(int a, int b, int c)
+getMedio():int

25

Pruebas de sistemas de informacin

Captulo 3. PRUEBAS DE CAJA BLANCA


Como se ha comentado en el captulo anterior, en las pruebas de caja blanca
el ingeniero de pruebas se interesa por conocer las regiones del cdigo que han
sido recorridas. As, si se encuentra con que una zona del cdigo no ha sido recorrida por los casos de prueba, se aadirn nuevos casos de prueba que fuercen
a que se pase por ah.

1. Medidas de la cobertura
La cobertura es la cantidad de cdigo recorrido por un conjunto de casos de
prueba. Existen multitud de formas de medir cunto cdigo se ha recorrido. A
continuacin se presentan algunos de ellos.
1.1.

Cobertura de sentencias
Este criterio se satisface cuando se recorren todas las sentencias del pro-

grama al menos una vez.


1.2.

Cobertura de decisiones, de ramas o de todos los arcos

Una condicin es un par de expresiones algebraicas relacionadas por un


operador relacional (<, >, =, >=, <=, <>).
Una decisin es una lista de condiciones conectadas por operadores lgicos
(AND, OR).
El criterio de cobertura de decisiones se satisface cuando cada decisin se
evala a true y a false al menos una vez.
A este criterio tambin se le llama de ramas (branch) o de arcos (all-edges).
El fragmento de cdigo mostrado en la Figura 6 se corresponde con la implementacin dada al mtodo getTipo en la clase Tringulo. Se alcanzar el criterio de cobertura de decisiones cuando todas las ramas de sus sentencias condicionales hayan sido recorridas.

27

Pruebas de sistemas de informacin

As, la decisin de la lnea 11 se considerar recorrida de acuerdo con este


criterio cuando se entre al bloque de las lneas 12 y 13 y se entre tambin al bloque de las lneas 15 y 16. Para que estas dos circunstancias acontezcan, debe
ocurrir que la decisin (i+j<=k || j+k<=i || i+k<=j) tome tanto valor true como
false. Para que sea true, basta con que sea true cualquiera de sus condiciones;
para que sea false, debern serlo las tres condiciones.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

public
if
if
if

int getTipo() {
(i==j) { tipo=tipo+1; }
(i==k) { tipo=tipo+2; }
(j==k) { tipo=tipo+3; }

if (i<=0 || j<=0 || k<=0) {


tipo=Triangulo.NO_TRIANGULO;
return tipo;
}
if (tipo==0) {
if (i+j<=k || j+k<=i || i+k<=j) {
tipo=Triangulo.NO_TRIANGULO;
return tipo;
} else {
tipo=Triangulo.ESCALENO;
return tipo;
}
}
if (tipo>3) {
tipo=Triangulo.EQUILATERO;
return tipo;
} else if (tipo==1 && i+j>k) {
tipo=Triangulo.ISOSCELES;
return tipo;
} else if (tipo==2 && i+k>j) {
tipo=Triangulo.ISOSCELES;
return tipo;
} else if (tipo==3 && j+k>i) {
tipo=Triangulo.ISOSCELES;
return tipo;
} else {
tipo=Triangulo.NO_TRIANGULO;
return tipo;
}
}

Figura 6. Cdigo del mtodo getTipo de la clase Tringulo

1.3.

Cobertura de condiciones

Este criterio requiere que cada decisin de cada condicin se evale a true y
a false al menos una vez.
Volviendo al ejemplo de la lnea 11 del fragmento de cdigo de la Figura 6,
los casos de prueba habrn cumplido el criterio de condiciones cuando i+j<=k
haya sido verdadero y falso, j+k<=i haya sido tambin verdadero y falso, e
i+k<=j haya sido tambin verdadero y falso, para lo cual se necesitara un mnimo de seis casos de prueba.

28

Pruebas de sistemas de informacin

1.4.

Cobertura de condiciones/decisiones (Decision/Condition coverage, o DCC)

Requiere que cada condicin de cada decisin se evale a true y a false al


menos una vez, y que cada decisin se evale a true y a false al menos una vez.
1.5.

Cobertura modificada de condiciones/decisiones (MC/DC).

Adems de requerir el criterio anterior, se requiere que cada condicin afecte independientemente a la decisin.
1.6.

Cobertura mltiple de condiciones (MCC)

Este criterio requiere que todas las condiciones tomen valor true y false, de
manera que se recorra la tabla de verdad completa de la decisin.
1.7.

Cobertura de todos los usos (all-uses)

Dada una variable x, un conjunto de casos de prueba verifica el criterio de


todos los usos para x si todos los posibles caminos que hay entre la definicin de
x y todos los usos de esta variable son recorridos.
1.8.

Cobertura de caminos

Este criterio requiere que se recorran todos los caminos linealmente independientes que se encuentren en el grafo de flujo de la unidad que se est probando. El nmero de caminos linealmente independientes coincide con la complejidad ciclomtica de McCabe, la cual puede calcularse contando el nmero de
instrucciones que crean ramas. En el cdigo del Figura 6, hay 11 instrucciones if,
con lo que la complejidad ciclomtica de ese fragmento de cdigo es 11. Este valor coincide con el nmero de regiones que pueden encontrarse en el diagrama
de flujo correspondiente al cdigo que se est probando: la Figura 7 muestra el
diagrama de flujo correspondiente a dicho fragmento de cdigo, en el que pueden apreciarse once reas (incluyendo la exterior).
Para alcanzar este criterio de cobertura en este ejemplo, deberan utilizarse
once casos de prueba adecuados que recorrieran todos los posibles caminos.

29

Pruebas de sistemas de informacin

1.9.

Cobertura de funciones

Este criterio se verifica cuando se ha llamado a todas las funciones y procedimientos.


1.10. Cobertura de llamadas
Se verifica cuando se han ejecutado todas las llamadas a a funciones y procedimientos. No debe confundirse con la cobertura de funciones: en la cobertura
de funciones contamos cuntas funciones de las que hay en nuestro programa
han sido llamadas, mientras que la cobertura de llamadas cuenta cuntas de las
llamadas a funciones que hay en el programa se han ejecutado.
1.11. Cubrimiento de bucles
Se verifica cuando todos los bucles se han ejecutados cero veces (excepto para bucles do..while), una vez y ms de una vez.
1.12. Cubrimiento de carrera
Comprueba el nmero de tareas o hilos que han ejecutado simultneamente
el mismo bloque de cdigo.
1.13. Cobertura de operadores relacionales
Comprueba si se han ejecutado los valores lmite en los operadores relacionales (>, <, >=, <=), ya que se asume la hiptesis de que estas situaciones son
propensas a errores.
1.14. Cobertura de tablas
Comprueba si se ha hecho referencia a todos los elementos de los arrays.
1.15. Cobertura basada en mutacin
Le dedicaremos a esto una seccin aparte.

30

Pruebas de sistemas de informacin

Figura 7. Diagrama de flujo para el cdigo del mtodo getType de la


Figura 6

31

Pruebas de sistemas de informacin

2. La mutacin
En el contexto de las pruebas del software, un mutante es una copia del programa que se est probando (programa original) al que se le ha introducido un
nico y pequeo cambio sintctico que no impide que el programa compile (por
ejemplo, cambiar un signo + por un * en una expresin aritmtica). As, puede
entenderse que el mutante es una versin defectuosa del programa original: es
decir, el mutante es el programa original, pero en el que se ha introducido o en
el que se ha sembrado un fallo.
El lado izquierdo de la Figura 8 muestra el cdigo del programa que vamos a
probar (Original) y el de algunos mutantes. En el lado derecho aparecen cuatro casos de prueba y los resultados de cada uno sobre las diferentes versiones
del programa. Obsrvese que:

El par (1,1) produce salidas diferentes en el programa original y en


los mutantes 1, 2 y 3: esto significa que este caso de prueba es bueno
porque ha encontrado los errores introducidos en esas tres versiones.

El par (0,0) encuentra solamente el error del mutante 3. Respecto de


la coleccin de mutantes mostrada en la figura, es un caso de prueba
algo peor que el (1,1), pues encuentra menos errores.

El mutante 4 ofrece exactamente la misma salida que el programa


original para todos los datos de prueba. Adems, nos resultar imposible encontrar un caso de prueba que consiga que la salida de este
mutante sea distinta.

32

Pruebas de sistemas de informacin

Cdigo

int suma(int a, int b)


{
Original
return a + b;
}
int suma(int a, int b)
Mutant 1 {
return a - b;
}
int suma(int a, int b)
Mutant 2 {
return a * b;
}
int suma(int a, int b)
Mutant 3 {
return a / b;
}
int suma(int a, int b)
Mutant 4 {
return a + b++;
}
(a) Un programa y unos mutantes

Datos de prueba (a,b)

Versiones

Versin

(1, 1)

(0, 0)

(-1, 0)

(-1, -1)

Original

-1

-2

Mutante 1

-1

Mutante 2

Mutante 3

Error

Error

Mutante 4

-1

-2

(b) Resultados con algunos datos de prueba

Figura 8. Un programa, varios mutantes y los resultados con algunos


casos de prueba

2.1.

Algo de terminologa

Dado un programa original y un conjunto de mutantes, se dice que un caso


de prueba mata un mutante cuando la salida del mutante es distinta de la del
programa original para ese caso de prueba. As pues, en la Figura 8, el caso de
prueba formado por el par (1,1) mata a los mutantes 1, 2 y 3, mientras que (0,0)
mata tan solo al mutante 3.
No hay ningn caso de prueba en nuestro test suite que sea capaz de matar
al mutante 4, por lo que se dice que este mutante est vivo. Adems, dado el
cambio introducido en el cdigo de este mutante, resultar imposible escribir un
caso de prueba que lo mate, por lo que se dice que el mutante es funcionalmente equivalente.
2.2.

La mutacin como criterio de cobertura

Dado un programa P formado por n lneas de cdigo y dos test suites t1 y t2


que sirven para probar P, podemos afirmar (con alguna salvedad que no merece
la pena entrar a discutir) que t1 es mejor que t2 si t1 recorre ms sentencias de P
que t2. As pues, la cobertura que un determinado conjunto de casos de prueba

33

Pruebas de sistemas de informacin

alcanza en un programa es un indicador de la calidad de ese conjunto de casos


de prueba.
Del mismo modo, cuantos ms mutantes mate un test suite, mejor es dicho
test suite. De hecho, se dice que un test suite es adecuado para la mutacin (mutation-adequate) cuando mata el 100% de los mutantes no equivalentes. As
pues, el grado de adecuacin a la mutacin se mide calculando el mutation score, utilizando la frmula de la Figura 9.
K
MS ( P, T ) =
( M E ) , where:

P : programa bajo prueba


T : test suite
K : nmero de mutantes muertos
M : nmero de mutantes generados
E : nmero de mutantes equivalentes

Figura 9. Clculo del mutation score

El objetivo de las pruebas utilizando mutacin consiste en construir casos de


prueba que descubran el error existente en cada mutante. As pues, los casos de
prueba sern buenos cuando, al ser ejecutados sobre el programa original y sobre los mutantes, la salida de stos difiera de la salida de aqul, ya que esto significar que las instrucciones mutadas (que contienen el error) han sido alcanzadas por los casos de prueba (o, dicho con otras palabras, que los casos de
prueba han descubierto los errores introducidos).
2.3.

Proceso de pruebas basado en mutacin

La Figura 10 muestra el proceso de mutacin propuesto por Offutt [12]. Las


lneas punteadas indican tareas manuales, mientras que las de trazo continuo
son tareas automatizables. Inicialmente se genera el conjunto de mutantes, el
conjunto de casos de prueba y se define un umbral que representa el porcentaje
mnimo de mutantes muertos que debe alcanzarse (el valor mnimo del mutation score). Entonces se ejecutan los casos de prueba sobre el programa original
y sobre los mutantes, y se calcula el porcentaje de mutantes muertos. Si no se ha
alcanzado el umbral previamente definido, se eliminan los casos de prueba que
no han matado mutantes y se generan casos de prueba nuevos, especialmente
dirigidos a matar los mutantes que han permanecido vivos.

34

Pruebas de sistemas de informacin

Progama
original P

Crear
mutantes M

Crear casos
de prueba T

Ejecutar T sobre
P

Ejecutar T sobre
cada mutante
vivo

Definir umbral

No

Corregir P

Se alcanz
el umbral?

Eliminar los
casos de prueba
ineficientes

S
No

P(T) es
correcta?
S

Fin

Figura 10. Proceso de pruebas usando mutacin propuesto por Offutt


[13]

El proceso anterior tiene una desventaja importante: si se encuentra que


P(T) no es correcta, P debe ser corregido y, los mutantes, generados de nuevo,
con el coste que supone esta tarea. As pues, como se ha discutido en [14], es
preferible utilizar el proceso descrito en la Figura 5.
Para matar a un mutante deben producirse tres condiciones:
-

Alcance: la sentencia mutada debe ser ejecutada por el caso de prueba.

Necesidad: entre la entrada y la salida del programa debe crearse un


estado intermedio errneo.

Suficiencia: el estado incorrecto debe propagarse hasta la salida del


programa.

La condicin de suficiencia puede ser difcil de conseguir en muchas ocasiones, lo que puede dificultar la obtencin de casos de prueba a un coste razona-

35

Pruebas de sistemas de informacin

ble. La mutacin dbil se queda en la condicin de necesidad para determinar


que un caso de prueba ha matado a un mutante: compara el estado intermedio
del mutante y el del programa original inmediatamente despus de haber ejecutado la instruccin mutada, marcando el mutante como muerto si los estados
son diferentes. Se ha comprobado experimentalmente que esta tcnica puede
ahorrar hasta el 50% del coste de las pruebas sin degradar excesivamente su
calidad.
2.4.

Operadores de mutacin

La generacin de mutantes se consigue aplicando operadores de mutacin


al cdigo fuente del programa que queremos probar. La Tabla 4 muestra algunos de los operadores de mutacin citados en Offutt et al. [13].
Operador
ABS
ACR
AOR
CRP
ROR
RSR
SDL
UOI

Descripcin
Sustituir una variable por el valor absoluto de dicha variable
Sustituir una referencia variable a un array por una constante
Sustitucin de un operador aritmtico
Sustitucin del valor de una constante
Sustitucin de un operador relacional
Sustitucin de la instruccin Return
Eliminacin de una sentencia
Insercin de operador unario (p.ej.: en lugar de x, poner x)

Tabla 4. Algunos operadores de mutacin clsicos

El nmero de mutantes que puede generarse a partir de un programa sencillo, de pocas lneas de cdigo, es muy grande (pinsese que el operador AOR,
por ejemplo, puede aplicarse a cada aparicin de un operador aritmtico en el
programa original), resultando tambin muy costosas tanto la ejecucin de los
casos de prueba con cada mutante como la comprobacin de la salida del programa. Por ello, se han realizado algunos estudios encaminados a disminuir los
costes de este tipo de pruebas, evidencindose que, aplicando pocos operadores,
se pueden conseguirse los mismos resultados que si se aplicaran muchos. Los
operadores ms efectivos son el ABS, 0 (sustitucin de una variable por el valor
0), <0 (sustitucin de una variable por un valor menor que 0), >0 (sustitucin
de una variable por un valor mayor que 0), AOR, ROR y UOI.
Adems, tambin se han propuesto operadores especficos para programas
escritos en lenguajes orientados a objeto, algunos de los cuales se muestran en
la Tabla 5 .

36

Pruebas de sistemas de informacin

Operador

Descripcin

AMC (Access Modifier


Change)
AOC (Argument Order
Change)

Reemplazo del modificador de acceso (por ejemplo: ponemos private


en lugar de public)
Cambio del orden de los argumentos pasados en la llamada a un mtodo (p.ej.: en lugar de Persona p=new Persona(Paco, Pil) poner
Persona p=new Persona(Pil, Paco)
Sustituir una referencia a una instancia de una clase por una referencia
a una instancia de una clase compatible (p.ej.: en vez de poner Persona
p=new Empleado(), poner Persona p=new Estudiante()).
Cambiar una instruccin de manejo de excepciones (try...catch) por un
sentencia que propague la excepcin (throw), y viceversa
Eliminacin de una instruccin de manejo de excepciones

CRT (Compatible Reference Type Replacement)


EHC (Exception Handling Change)
EHR (Exception
Handgling Removal)
HFA (Hiding Field
variable Addition)
MIR (Method Invocation Replacement)
OMR (Overriding
Method Removal)
POC (Parameter Order
Change)
SMC (Static Modifier
Change)

Aadir en la subclase una variable con el mismo nombre que una variable de su superclase
Reemplazar una llamada a un mtodo por una llamada a otra versin
del mismo mtodo
Eliminar en la subclase la redefinicin de un mtodo definido en una
superclase
Cambiar el orden de los parmetros en la declaracin de un mtodo
(p.ej.: poner Persona(String apellidos, String nombre) en vez de Persona(String nombre, String apellidos)
Aadir o eliminar el modificador static

Tabla 5. Algunos operadores de mutacin para orientacin a objetos

3. Ejercicios
1) Escriba casos de prueba para lograr cobertura de sentencias, de condiciones y de caminos para el problema del tringulo.
2) Escriba casos de prueba para matar a todos los mutantes del ejercicio 1
del captulo anterior.
3) Se dice que un criterio de cobertura C1 subsume a otro C2 si, para todo
programa P, cualquier caso de prueba T que satisface C1 satisface tambin C2.
Proponga algunos operadores de mutacin para conseguir que la mutacin
subsuma al criterio de decisiones. Se puede conseguir lo mismo para el criterio
de condiciones?
4) Para diagramas de flujo pueden definirse criterios de cobertura como Todos los caminos, Todos los arcos o Todos los nodos. Existen relaciones de subsuncin entre estos criterios?

37

Pruebas de sistemas de informacin

Captulo 4. LOS VALORES INTERESANTES


En este captulo se introduce y profundiza en el concepto de valor interesante, se revisan dos tcnicas para utilizarlos y se describen algunos criterios de
cobertura para valores.

1. Un estudio inicial del problema del tringulo


Si queremos aplicar correctamente el proceso de pruebas descrito en la
Figura 5 (pgina 23) al problema del tringulo (la implementacin de su mtodo
getTipo se daba en la Figura 6, pgina 28), el ingeniero de pruebas deber escribir casos de prueba que utilicen, como parmetros de los mtodos setI, setJ y
setK, buenos valores, en el sentido de que con ellos se recorra la mayor cantidad posible de cdigo fuente, en funcin del criterio de cobertura elegido.
public void testEQ1() {
Triangulo t=new Triangulo();
t.setI(5);
t.setJ(5);
t.setK(5);
assertTrue(t.getTipo()==t.EQUILATERO);
}

public void testES1() {


Triangulo t=new Triangulo();
t.setI(4);
t.setJ(3);
t.setK(5);
assertTrue(t.getTipo()==t.ESCALENO);
}

public void testEQ2() {


Triangulo t=new Triangulo();
t.setI(3);
t.setJ(3);
t.setK(3);
assertTrue(t.getTipo()==t.EQUILATERO);
}

public void testES2() {


Triangulo t=new Triangulo();
t.setI(3);
t.setJ(4);
t.setK(5);
assertTrue(t.getTipo()==t.ESCALENO);
}

public void testIS1() {


Triangulo t=new Triangulo();
t.setI(3);
t.setJ(5);
t.setK(5);
assertTrue(t.getTipo()==t.ISOSCELES);
}

public void testNT1() {


Triangulo t=new Triangulo();
t.setI(1);
t.setJ(2);
t.setK(3);
assertTrue(t.getTipo()==t.NO_TRIANGULO);
}

public void testIS2() {


Triangulo t=new Triangulo();
t.setI(5);
t.setJ(3);
t.setK(5);
assertTrue(t.getTipo()==t.ISOSCELES);
}

public void testNT2() {


Triangulo t=new Triangulo();
t.setI(0);
t.setJ(2);
t.setK(3);
assertTrue(t.getTipo()==t.NO_TRIANGULO);
}

Figura 11. Ocho casos de prueba en JUnit para el problema del


Tringulo

La Figura 11 muestra ocho casos de prueba en formato JUnit para este problema. Como se observa, se han escrito dos casos para cada una de las posibles

39

Pruebas de sistemas de informacin

salidas del mtodo getTipo. Al medir la cobertura de sentencias alcanzada por


estos casos de prueba, se observa que se recorre el 88% de ellas (Figura 12).

Figura 12. Sentencias ejecutadas ( ) y no ejecutadas (


por los casos de prueba de la Figura 11

) en getTipo

Puesto que no alcanzamos el umbral del 100% con este criterio de cobertura,
de acuerdo con la discusin de Cornett que mencionbamos en la pgina 21,
debemos escribir nuevos casos de prueba que ejecuten las lneas no recorridas,
que son las que se sealan con la marca

en la Figura 12. As, debemos escribir

un caso que corresponda a un tringulo issceles tal que la longitud del tercer
lado sea menor que la suma de los otros dos (i+j>k), y otro que corresponda al
no tringulo que se determina en las ltimas lneas.

40

Pruebas de sistemas de informacin

La adicin de un nuevo caso con los valores (3, 3, 1) recorre las primeras lneas indicadas, y el caso (5, 5, 10) recorre las ltimas. Por tanto, con esta pequea batera de casos conseguiramos una cobertura de sentencias del 100%.
Con este mismo conjunto de casos de prueba, tambin conseguimos cobertura
del 100% en el criterio todos los usos (descrito en la pgina 29).
Sin embargo, si utilizamos la mutacin como criterio de cobertura, estos casos de prueba matan tan slo el 2% de los mutantes que MuJava genera. MuJava es una herramienta para realizar pruebas de caja blanca de programas Java
utilizando mutacin [15]. Para el problema del tringulo, MuJava genera 479
mutantes tradicionales (correspondientes a aplicar los operadores mostrados
en la Tabla 4, pgina 36) y 82 mutantes de clase (correspondientes a los operadores que explotan especficamente las caractersticas de los lenguajes de programacin orientados a objeto, mostrados en la Tabla 5, pgina 37).
La Figura 13 muestra, en un pantallazo de MuJava, el cdigo de la clase
Tringulo y de unos de sus mutantes tradicionales: obsrvese que la instruccin
modificada (se ha sustituido el operador <= por < en la lnea 59) supone, en el
mutante la simulacin de un error introducido involuntariamente por el programador. Puesto que el objetivo de los casos de prueba es encontrar errores en
el cdigo, si seguimos el criterio de la mutacin deberamos escribir al menos un
caso de prueba que encuentre el error introducido en la zona inferior de la
Figura 13.

41

Pruebas de sistemas de informacin

Figura 13. Cdigo de la clase Tringulo original (arriba) y del mutante


ROR_112 generado por MuJava (abajo)

2. Concepto de valor interesante


Desde el punto de vista del testing, un valor interesante es cualquier valor
que el ingeniero de pruebas considera que debe ser utilizado para sus casos de
prueba [16]. Como ya se ha mencionado, es preciso tener cierta picarda para
elegir estos valores, ya que deben ir utilizndose aquellos que vayan ejercitando
todas las regiones del cdigo.
As pues, y volviendo a los dos casos de prueba de la Figura 16, la terna de
valores (5, 5, 5) no es interesante porque tenemos con anterioridad la (3, 3, 3).
Para proponer valores realmente interesantes existen varias tcnicas bien
conocidas que, no obstante, vamos a recordar en las siguientes secciones.
2.1.

Clases de equivalencia

Con esta tcnica, se divide el dominio de valores de entrada en un nmero


finito de clases de equivalencia. Se asume que el comportamiento de la CUT ante un elemento cualquiera de una clase de equivalencia dada ser el mismo.

42

Pruebas de sistemas de informacin

2.2.

Valores lmite

Esta tcnica complementa a la anterior: en lugar de elegir cualquier valor de


la clase de equivalencia, se seleccionan los valores situados en los lmites de las
clases de equivalencia.
Tanto la tcnica de valores lmite como la de clases de equivalencia pueden
ser aplicadas al conjunto de salida, de forma que lo que se particiona no es el
dominio de entrada, sino el de salida, con lo que los casos de prueba que se
construyan (que sern las entradas del programa bajo prueba) debern ser capaces de generar las salidas en cada una de las clases de equivalencia de salida.
2.3.

Fundamento matemtico

Hoffman et al. [17] exploran los fundamentos matemticos de las tcnicas de


valores lmite y clases de equivalencia. Siendo D=(d0, , dn-1) un dominio de
datos de entrada no vaco y ordenado para un cierto parmetro, se definen las
siguientes funciones:
{d k 1, d n k }, si n es par y k < n / 2

{d ( n / 2) 1, d n / 2 }, si n es par y k n / 2
lmites ( D, k ) =
{d k 1, d n k }, si n es impar y k < (n + 1) / 2
{d ( n 1) / 2 }, si n es impar y k ( n + 1) / 2

lmites ( D, k )* =

Ulmites(D, i)
i =1

Ecuacin 2

Ecuacin 1

Para un conjunto de dominios con esas caractersticas, se definen las siguientes dos funciones:
k

lmites ( D0 ,..., Dm 1, k ) = lmites ( D0 , k ) ... lmites ( Dm 1, k )

lmites ( D0 ,..., Dm 1, k )* =

Ulmites(D ,..., D
0

m 1, k )

i =1

Ecuacin 3

Ecuacin 4

Supongamos que tenemos los dominios X={0, 1, 2, 3, 4} e Y={0, 1, 2, 3}. Los


valores de las dos primeras ecuaciones anteriores son:
D (dominio)

lmites(D, 1)

lmites(D, 2)

lmites(D, 3)

{0, 4}

{1, 3}

{2}

{0, 3}

{1,2}

{1,2}

lmites(D,1)*
{0,4}

lmites(D,2)*
{0, 4, 1, 3}

lmites(D,3)*
{0,4, 1, 3, 2}

{0,3}

{0, 3, 1, 2}

{0, 3, 1, 2}

Tabla 6. Aplicacin de la Ecuacin 1 y de la Ecuacin 2

Si combinamos los dos dominios, X e Y, podemos aplicar la Ecuacin 3:

43

Pruebas de sistemas de informacin

lmites(X, Y, 1)

lmites(X, Y, 2)

lmites(X, Y, 3)

{(0,0), (0, 3), (4, 0), (4, 3)}

{(1, 1), (1, 2), (3, 1), (3, 2)}

{(2, 1), (2, 2)}

Tabla 7. Aplicacin de la Ecuacin 3

Y, a partir de la Tabla 7, podemos ya aplicar la Ecuacin 4:


lmites(X, Y, 1)*

lmites(X, Y, 2)*

lmites(X, Y, 3)*

{(0,0), (0, 3), (4, 0), (4, 3)}

{(0,0), (0, 3), (4, 0), (4, 3) (1, 1),

{(0,0), (0, 3), (4, 0), (4, 3) (1,

(1, 2), (3, 1), (3, 2)}

1), (1, 2), (3, 1), (3, 2), (2, 1),


(2, 2)}

Tabla 8. Aplicacin de la Ecuacin 4

Los pares de valores que tenemos en la tercera columna de la Tabla 8 representan casos de prueba: cada elemento del par representa un valor de cada uno
de los dominios.
En el mismo artculo, los autores definen tambin el concepto de permetro,
que es muy similar al de los lmites descrito, slo que, adems de los valores lmite, tambin se aaden a los casos de prueba valores pertenecientes al interior
de cada dominio.

3. Criterios de cobertura para valores


Adems de los criterios de cobertura de cdigo, tambin pueden definirse
criterios de cobertura para los valores de los parmetros de los casos de prueba
en funcin de su inters. Con estos criterios, viene a medirse el grado en que
los diferentes valores interesantes seleccionados se utilizan en la batera de casos de prueba.
A continuacin se presentan algunos criterios de cobertura para valores.
3.1.

Cada uso (each-use, o 1-wise)

Es el criterio ms simple. Se satisface cuando cada valor interesante de cada


parmetro se incluye, al menos, en un caso de prueba.
Supongamos que, para el ejemplo del tringulo, el ingeniero de pruebas ha
seleccionado como valores interesantes el conjunto {0, 1, 2, 3, 4, 5} para cada
uno de los lados. Un conjunto de casos de prueba que satisface el criterio 1-wise
estara formado por las siguientes ternas:

44

Pruebas de sistemas de informacin

1. (0, 1, 2) con este, en los prximos casos no sera necesario probar


con el 0 en la primera posicin, ni con el 1 en la segunda, ni con el 2
en la tercera
2. (1, 0, 2)
3. (2, 3, 4)
4. (2, 4, 3)
5. (3, 5, 0)
6. (4, 2, 1)
7. (3, 0, 5) este caso vuelve a emplear el 0 en la segunda posicin; sin
embargo, es necesario utilizarlo para probar con el 5 en la tercera posicin
8. (5, 0, 1)
Como se observa, el 0 aparece en la primera, segunda y tercera posiciones
(casos 1, 2 y 5); el 1 aparece en la segunda, primera y tercera (casos 1, 2 y 6); el 2
aparece en las posiciones tercera, primera y segunda (casos 1, 3 y 6); el 3 aparece tambin en todas las posiciones (casos 5, 3 y 4); el 4 aparece en los casos 3, 4
y 6; por ltimo, el 5 aparece en los casos 8, 5 y 7.
Desafortunadamente, la batera de casos formada por las ternas (0, 0, 0), (1,
1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4) y (5, 5, 5) cumple tambin el criterio 1-wise. As
pues, la calidad del conjunto de casos puede ser muy mala si no ponemos cuidado al escribirlos todos.
3.2.

pair-wise (o 2-wise)

Este criterio requiere que cada posible par de valores interesantes de cualesquiera dos parmetros sea incluido en algn caso de prueba. Se trata de un criterio ampliamente utilizado. La siguiente figura muestra un algoritmo sencillo
que genera casos de prueba con cobertura pair-wise.

45

Pruebas de sistemas de informacin

testSuite =
PairTable[] pairTables=buildPairTables(a, b, c)
while p pairTables / p.numberOfVisits=0
i=0
found = false
while not found
if combination[i] visits p
testSuite= testSuite {combination[i]}
visit

pairs

of

combination[i]

on

pairTables
found = true
end if
i=i+1
end while
end while

Figura 14. Un algoritmo para pair-wise

Supongamos que, para el problema del Tringulo, utilizamos los valores {0,
1, 2, 3} para asignar la longitud de sus tres lados. Tendramos las tres siguientes
tablas de pares:
i/j
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(3, 0)
(3, 1)
(3, 2)
(3, 3)

i/k
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(3, 0)
(3, 1)
(3, 2)
(3, 3)

j/k
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(3, 0)
(3, 1)
(3, 2)
(3, 3)

Figura 15. Tablas de pares para el problema del Tringulo

A partir de las tablas de pares, debemos ir construyendo casos de prueba


que vayan visitando cada par el menor nmero posible de veces. Por ejemplo,
podramos elegir los tres pares (0, 0) de las tres tablas de arriba, con lo que aadiramos el caso de prueba (0, 0, 0) al conjunto, y marcaramos esos tres pares
en las tablas, con objeto de no volver a visitarlos.

46

Pruebas de sistemas de informacin

3.3.

t-wise

Es una extensin del 2-wise, en la que cada combinacin posible de valores


interesantes de los t parmetros de la operacin de que se trate se incluye en
algn caso de prueba. En nuestro ejemplo, ninguna de las operaciones del tringulo toma ms de un parmetro, por lo que la cobertura 2-wise sera la misma
que t-wise.
3.4.

N-wise

Es un caso especial de t-wise: siendo N el nmero de parmetros, N-wise se


satisface cuando todas las combinaciones posibles de todos los parmetros se
incluyen en casos de prueba. Es decir, en t-wise, tN.

4. Casos de prueba redundantes


Continuando con el socorrido ejemplo del Tringulo, si realizsemos un seguimiento de los casos de prueba testEQ1 y testEQ2 (presentados en la Figura
11, pero que reproducimos en la Figura 16 para comodidad del lector) observaramos que recorren exactamente las mismas sentencias y que matan exactamente a los mismos mutantes. El caso testEQ2, por tanto, no aporta nada a
nuestro proceso de pruebas respecto del caso testEQ1.
public void testEQ1() {
Triangulo t=new Triangulo();
t.setI(5);
t.setJ(5);
t.setK(5);
assertTrue(t.getTipo()==t.EQUILATERO);
}

public void testEQ2() {


Triangulo t=new Triangulo();
t.setI(3);
t.setJ(3);
t.setK(3);
assertTrue(t.getTipo()==t.EQUILATERO);
}

Figura 16. Dos de los casos de prueba del Tringulo, que son
redundantes

As pues, a la hora de escribir casos de prueba para probar cualquier clase,


es necesario aplicar cierto sentido comn para utilizar valores buenos, en el
sentido de que cada nuevo caso de prueba que introduzcamos recorra una zona
del cdigo que no haya sido recorrida con por los casos de prueba anteriores o,
si aplicamos el criterio de la mutacin, que mate mutantes que no haban sido
matados por los casos de prueba anteriores.
El tema de los casos de prueba redundantes, por otro lado, provoca el problema de su minimizacin. En el ejemplo mencionado de la Figura 16, es claro
que un solo caso de prueba hara exactamente las mismas funciones que los dos

47

Pruebas de sistemas de informacin

que se muestran. Hay situaciones en las que se dispone de un nmero muy


grande de casos de prueba entre los cuales se encuentran varios subconjuntos
de casos que ejercitan exactamente las mismas sentencias o que matan exactamente el mismo conjunto de mutantes. As pues, en ocasiones es necesario disponer de un conjunto de casos de prueba que consiga la misma cobertura que
otro, teniendo ste un mayor nmero de elementos. Este problema se conoce
con el nombre de Reduccin ptima del conjunto de casos (Optimal test-suite
reduction), que ha sido ampliamente estudiado en la literatura . El problema
resulta ser NP-completo, por lo que su solucin ptima no es alcanzable en
tiempo polinomial, si bien en las referencias citadas se pueden encontrar diversos algoritmos (normalmente voraces) que logran soluciones buenas en tiempos
razonables.
4.1.

Reduccin del conjunto de casos basado en mutacin

El siguiente algoritmo recibe como entradas el conjunto completo de casos


de prueba, la clase bajo prueba (CUT) y el conjunto completo de mutantes de la
CUT.
En la lnea 2, ejecuta todos los casos de la prueba contra la CUT y contra los
mutantes, guardando los resultados en testCaseResults. El algoritmo est ya
preparado para seleccionar, en varias iteraciones, los casos de la prueba que matan a ms mutantes, lo cual se hace en el bucle de las lneas 5 a 18. La primera
vez que el algoritmo entra en el bucle y llega la lnea 7, el valor de n (que se utiliza como condicin de parada las iteraciones) es |mutants|: en este caso especial,
el algoritmo busca un caso de prueba que mate a todos los mutantes. Si lo encuentra, el algoritmo agrega el caso de la prueba a requiredTC, actualiza el valor
de n y termina; si no, disminuye n (lnea 16) y entra nuevamente en el bucle.
Supongamos que n es inicialmente 100 (es decir, hay 100 mutantes de la
clase bajo prueba), y supongamos tambin que el algoritmo no encuentra casos
de prueba que matan a mutantes hasta n=30. Con este valor, la funcin getTestCasesThatKillN (llamada en la lnea 7) devuelve tantos casos de prueba como casos de la prueba matan a n mutantes diferentes: esto es, si hay dos casos
de prueba (tc1 y tc2) que matan a los mismos 30 mutantes, getTestCasesThatKillN devuelve solamente un caso de la prueba (por ejemplo, tc1). Si la intersec-

48

Pruebas de sistemas de informacin

cin de los mutantes matados por tc1 y tc2 no es vaca, el algoritmo devuelve un
conjunto formado tc1 y tc2.
Cuando se encuentran casos de prueba que matan n mutantes, se agregan a
la variable requiredTC (lnea 9) y se eliminan los mutantes muertos (lneas 1013). De este modo, el algoritmo no vuelve a considerar los mutantes que han
sido muertos en iteraciones anteriores.
1. reduceTestSuite(completeTC : SetOfTestCases, cut : CUT, mutants : SetOfMutants) :
SetOfTestCases
2. testCaseResults = execute(completeTC, cut, mutants)
3. requiredTC =
4. n=|mutants|
5. while (n>0)
6. mutantsNowKilled =
7. testCasesThatKillN = getTestCasesThatKillN(completeTC, n, mutants, mutantsNowKilled,
testCaseResults)
8. if |testCasesThatKillN>0| then
9. requiredTC = requiredTC testCasesThatKillN
10. for i=1 to |testCasesThatKillN|
11.
testCase = testCasesThatKillN[i]
12.
testCase.removeAllTheMutantsItKills()
13. next
14. n = |mutants|-|mutantsNowKilled|
15. else
16. n = n 1
17. end if
18. end_while
19. return requiredTC
20.end

Figura 17. Algoritmo para minimizar el conjunto de casos de prueba

A la funcin encargada de recoger el conjunto de casos de prueba que matan


a n mutantes se la llama en la lnea 7 de la figura anterior, y se detalla en la
Figura 18. Recorre los elementos contenidos en testCaseResults y toma aquellos
casos cuya lista de killedMutants (Figura 17) tenga n elementos.

49

Pruebas de sistemas de informacin

1. getTestCasesThatKillN(completeTC : SetOfTestCases, n : int, mutants : SetOfMutants,


mutantsNowKilled : SetOfMutants,
testCaseResults: SetOfTestCaseResults)
2. testCasesThatKillN =
3. for i=1 to |testCaseResults|
4. testCaseResult = testCaseResults[i]
5. if |testCaseResult.killedMutants| == n then
6.
testCasesThatKillN = testCasesThatKillN testCaseResult.testCaseName
7.
mutantsNowKilled = mutantsNowKilled testCaseResult.killed.Mutants
8.
mutants = mutants mutantsNowKilled
9.
for j=1 to | testCaseResults |
10.
aux = testCaseResults[j]
11.
if aux.testCaseName testCaseResult.testCaseName then
12.
aux.remove(mutantsNowKilled[i]
13.
end_if
14. next
15. end_if
16. next
17. return testCasesThatKillN
18. end

Figura 18. Recuperacin de los casos que matan n mutantes


4.1.1

Ejemplo

La Figura 19 muestra los resultados de ejecutar un conjunto de casos de


prueba sobre una clase original y sus mutantes. La celda (i,j) se marca con un
aspa si el caso de prueba (que aparece en la columna j) mata al mutante (que
aparece en la fila i-sima). Los algoritmos vistos trabajan con estructuras de
datos de este estilo para realizar la minimizacin del conjunto de casos. En la
parte inferior de la figura aparece el conjunto reducido de casos de prueba.

Figura 19. Tabla de mutantes muertos por un conjunto de casos de


prueba

50

Pruebas de sistemas de informacin

4.2.

Algoritmo HGS

Harrold, Gupta y Soffa [18] proponen un algoritmo voraz (conocido como


HGS) para obtener, a partir de un conjunto de casos de prueba dado, otro nuevo
conjunto con menor tamao que conserve los requisitos deseados del conjunto
original.
Los pasos principales de este algoritmo son:
1) Inicialmente, todos los requisitos estn no marcados.
2) Aadir al resultado los casos de la prueba que verifican un requisito, y
marcar los requisitos cubiertos por los casos seleccionados.
3) Ordenar los requisitos no marcados de acuerdo con el nmero de casos
que satisfacen ese requisito. Si varios requisitos son satisfechos por varios casos de prueba, seleccionar el caso de la prueba que marque ms
requisitos. Marcar los requisitos satisfechos por los casos seleccionados.
Eliminar casos redundantes, que son los que no cubren ms requisitos
no marcados.
4) Repetir el paso 3) hasta que todos los requisitos de prueba estn marcados.
4.3.

Mejoras de Gupta

Con diversos colaboradores, Gupta ha propuesto varias mejoras al algoritmo


anterior:

Con Jeffrey [19], Gupta le agrega redundancia selectiva. La redundancia selectiva permite seleccionar los casos de prueba que, para
cualquier requisito dado, proporciona la misma cobertura que otro
caso previamente seleccionado. As, quiz T' alcance el criterio de
condiciones, pero quiz no el de todos los mutantes; por tanto, un
nuevo caso t puede ser aadido a T' si aumenta la cobertura en cuanto a mutantes: ahora, T' no aumentar el criterio de condiciones, pero
s el de mutantes.

Con Tallam [20], la seleccin de los casos de la prueba se basa en tcnicas de Anlisis de Conceptos. Segn los autores, este algoritmo obtiene un conjunto reducido con el mismo tamao y en un tiempo similares al algoritmo HGS original.

51

Pruebas de sistemas de informacin

4.4.

Algoritmo de Heimdahl y George

Heimdahl y George [21] tambin proponen un algoritmo voraz para reducir


el conjunto de casos de prueba. Bsicamente, toman un caso al azar, lo ejecutan
y comprueban la cobertura alcanzada. Si ste es mayor que la cobertura ms alta
alcanzada, lo agregan al conjunto resultado. El algoritmo se repite cinco veces
para obtener cinco conjuntos reducidos distintos, quedndose con el ms pequeo. Puesto que el azar es un componente esencial de este algoritmo, la buena
calidad de los resultados no est garantizada.
4.5.

Algoritmo de McMaster y Memon

McMaster y Memon [22] presentan tambin un algoritmo voraz. El parmetro considerado para incluir los casos de prueba en el conjunto reducido se basa
en las pilas de llamadas nicas que los casos de prueba producen en el programa bajo prueba.

5. Ejercicios
1) Suponga que disponemos de un sistema como el mostrado en la figura.
Proponga valores interesantes de tipo Persona para las operaciones add y setJefe del tipo Proyecto.
{incluido}

Proyecto

*
miembros

+add(p:Persona)
+setJefe(p:Persona)

jefe

Persona

categora

<<enum>>
Categora

nombre:String
apellidos:String
fechaNac:Date

2) Proponga una serie de valores interesantes para el tringulo y para el


problema de calcular el mximo que se propuso en un captulo anterior. (a)
Combine dichos valores para obtener casos de prueba cumpliendo los criterios
1-wise choice y pair-wise. (b) Ejecute los casos de prueba y compare la cobertura de cdigo fuente que alcanza cada conjunto de casos utilizando sentencias y
mutantes. (c) En alguno de los dos conjuntos hay casos de prueba redundantes? En caso afirmativo, respecto de qu criterio de cobertura? Los casos redundantes respecto de un criterio, lo son tambin respecto del otro?

52

Pruebas de sistemas de informacin

Captulo 5. ESTRATEGIAS DE COMBINACIN PARA


LA GENERACIN DE CASOS DE PRUEBA

Las estrategias de combinacin son mtodos que construyen los casos de


prueba combinando los valores interesantes de los diferentes objetos que se pasan como parmetros mediante algn algoritmo especfico.

1. Estrategias de generacin de casos de prueba


Grindal et al. presentan un estudio sobre 16 estrategias de combinacin, que
representan grficamente de la siguiente forma [16]:

Figura 20. Clasificacin de estrategias de combinacin

Como se ve, las tcnicas se clasifican segn su algoritmo en deterministas


(generan siempre los mismos casos de prueba) y no deterministas (el azar cumple un papel importante, por lo que no se garantiza que en dos ejecuciones del
algoritmo se genere el mismo conjunto de casos).
De forma general, el objetivo de todas estas estrategias es conseguir bateras
buenas de casos de prueba (donde, como siempre, el concepto de bondad depender finalmente del criterio de cobertura elegido).

53

Pruebas de sistemas de informacin

2. Estrategias no deterministas
En este tipo de estrategias, el azar cumple siempre un papel importante en
la determinacin de qu casos de prueba se generarn. As, no se asegura que
dos ejecuciones del mismo algoritmo produzcan siempre los mismos resultados.
2.1.

AETG: Automatic efficient test generator

El siguiente algoritmo genera casos de prueba para lograr cobertura pairwise, donde el valor de k se fija arbitrariamente. Cuanto mayor es k, menor es el
tamao del conjunto de casos, si bien a partir de k=50, el tamao del conjunto
permanece estable.
Se parte de un conjunto T de casos de prueba
Sea UC el conjunto de pares de valores de dos parmetros cualesquiera todava no cubiertos
por los casos preseleccionados
while UC
UC={pares de valores no cubiertos por T}
selectedTestCase=
for i=1 to k
Seleccionar la variable y el valor incluido en ms pares de UC
Ordenar aleatoriamente el resto de variables
Para cada variable determinada en el paso 5, seleccionar el valor incluido en ms pares de UC
y crear as un caso de prueba, tc
if tc visita ms pares que selectedTestCase then
selectedTestCase=tc
endIf
endFor
marcar en UC los pares cubiertos por selectedTestCase
T=T {selectedTestCase}
endWhile

Figura 21. Algoritmo AETG

2.2.

Algoritmos Genticos

De forma general, los algoritmos genticos constituyen un mtodo de resolucin de problemas de minimizacin. Parten de una solucin inicial, que se va
aproximando a la ptima segn una serie de iteraciones. De la solucin inicial
van construyndose soluciones mejores de acuerdo con una funcin objetivo
(fitness).

54

Pruebas de sistemas de informacin

2.2.1

Algoritmos Genticos (I)

Pargas et al. utilizan el algoritmo mostrado en la Figura 22 para lograr criterios de cobertura altos.
En la primera lnea se calcula CDGPaths, que representa el grafo de dependencias de control del programa que se va a probar. Un grafo de dependencia de
control es un grafo dirigido acclico cuyos nodos representan sentencias y cuyos
arcos representan dependencias de control entre sentencias. Un nodo Y depende por control de otro X si y slo si: (1) cualquier nodo intermedio en el camino
de X a Y est postdominado por Y; y (2) X no est postdominado por Y. Se dice
adems que un nodo X est postdominado por otro Y si para llegar desde X a la
salida es preciso pasar siempre por Y.
A continuacin se inicializa Scoreboard, que guarda el registro de los requisitos de prueba (TestReq) satisfechos. Scoreboard puede ser un vector de bits si
se desea lograr cobertura de sentencias, un vector de enteros si deseamos conocer la frecuencia de ejecucin de cada sentencia o, en general, una estructura de
datos adecuada al criterio de obertura considerado.
El siguiente paso es la generacin de la poblacin inicial (conjunto inicial de
los valores de entrada). A continuacin (bucle de las lneas 4 a 14), comienza el
proceso de generacin de los casos de prueba, bastante legible sin mayor explicacin. Como excepcin, hay que resaltar que el clculo del fitness se hace en
funcin del nmero de nodos de CDGPaths alcanzados por el caso de prueba
teniendo en cuenta el requisito de prueba actual (variable r en el algoritmo).

55

Pruebas de sistemas de informacin

1.

Crear CDGPaths

2. Crear e inicializar Scoreboard


3. Generar CurPopulation
4. while haya requisitos de prueba no marcados and se est en tiempo
5.

seleccionar un requisito de prueba r del conjunto TestReq

6.

while r no est marcado and no se supere el mximo de intentos

7.

calcular el fitness de de CurPopulation usando CDGPaths

8.

ordenar CurPopulation segn su fitness

9.

seleccionar los padres para crear la NewPopulation

10.

generar NewPopulation

11.

ejecutar el programa con cada elemento de NewPopulation

12.

actualizar Scoreboard y marcar aquellos requisitos que se hayan satisfecho

13.

endwhile

14. endwhile
15. final = conjunto de casos de prueba que satisfacen TestReq
16. devolver (TestReq, final)

Figura 22. Algoritmo de generacin de casos de prueba de


2.2.2

Algoritmos Genticos (II)

Shiba et al. [23] proponen el algoritmo gentico mostrado en la Figura 23.


Elite es el conjunto de los mejores individuos de la poblacin, y se va recalculando en cada iteracin; Pmating representa la poblacin siguiente, que procede
de cruces de P.
1.

Crear poblacin inicial P con m candidatos

2. Calcular fitness de P
3. while no se cumpla la condicin de parada
4.

Elite= n mejores individuos de P

5.

Aplicar Selection a los individuos de P para crear Pmating, con m-n individuos

6.

Cruzar Pmating

7.

Mutar Pmating

8.

P=Elite + Pmating

9.

Evaluar P

10.

if fitness(P) se ha estancado mutar masivamente P

11. endwhile
12. devolver el mejor caso

Figura 23. Algoritmo de generacin de casos de prueba de

56

Pruebas de sistemas de informacin

2.2.3

Algoritmo de las hormigas

El algoritmo de las hormigas representa los casos de prueba en un grafo como el siguiente:

Figura 24. Representacin de los casos de prueba en forma de grafo

Cada nodo pi representa un parmetro, y cada arco Vj,i representa el j-simo


valor interesante del parmetro i-simo. Cada camino desde el nodo inicial hasta el nodo objetivo se asocia con un caso de prueba. As, un posible caso de
prueba para el problema mostrado en la figura anterior vendra determinado
por {V1,1, V2,1, , V1,n-1, V2,n}.
El grafo es recorrido por un conjunto de hormigas. Cuando una hormiga alcanza el nodo objetivo, se deposita en cada arco de los que ha visitado una cantidad de feromonas proporcional a la calidad del solucin. Si una hormiga tiene
que elegir entre diferentes arcos, se va por aquel que tenga ms feromonas.
Como al principio todos los arcos no tienen feromonas, se calcula una heurstica para cada arco, que no cambia durante el algoritmo, segn la siguiente
ecuacin:

hi , j =

C i , max C i , j + 1
C i , max C i , min + 1

En la ecuacin, Ci,j representa el nmero de casos de prueba que contienen el


valor Vi,j. La idea de la heurstica es que los parmetros que aparecen menos
veces sean aadidos a los nuevos casos de prueba.
El algoritmo para la generacin de casos es el siguiente:

57

Pruebas de sistemas de informacin

1.

Calcular heursticas de cada arco

2. Inicializar feromonas
3. while no se alcance la condicin de parada
4.

for i=1 to |hormigas|

5.

generar un caso de prueba Sk

6.

evaluar Sk

7.

depositar feromonas

8.

endfor

9.

actualizar feromonas

10.

if la solucin se ha estancado then inicializar feromonas

11. endwhile
12. devolver el mejor caso

Figura 25. Algoritmo de las hormigas

El paso indicado en la lnea 5 (generar un caso de prueba) lo realiza cada


hormiga segn la heurstica y feromonas de cada arco, de acuerdo con la siguiente funcin de probabilidad:

[ ] [ ]
=
[ ] [ ]

Pi , j

i, j

vi

h =1

i, j

i ,h

, en donde vi es el nmero de posibles valores del pa-

i,h

rmetro pi; i,j y i,j son, respectivamente, el valor de la heurstica asignada al eje
i,j y la cantidad de feromona; y son factores de peso asignados en funcin de
la importancia que quiera darse a la heurstica o a la feromona.
La actualizacin de las feromonas se realiza cuando cada hormiga ha generado un caso de prueba y se hace con la siguiente ecuacin:

i , j = i , j + i , j + i, j
Adems de estas ecuaciones, se utilizan otras para representar las tasas de
persistencia y evaporacin de las feromonas.

3. Estrategias deterministas
En estas estrategias, dos ejecuciones del mismo algoritmo producen siempre
los mismos resultados con el mismo conjunto de entradas. Se describen a continuacin algunas de esta categora.

58

Pruebas de sistemas de informacin

3.1.

Each choice

En esta estrategia, se incluye cada valor de cada parmetro en al menos un


caso de prueba: en cada iteracin, se escoge un valor que no haya sido utilizado
en casos de prueba anteriores. Se logra cobertura 1-wise.
3.2.

Base choice

Se construye manualmente un caso de prueba base, que contiene los valores


ms importantes de cada parmetro. A partir de ste, se construyen nuevos casos de prueba variando los valores de un parmetro en cada iteracin. Esencialmente, este algoritmo es exactamente igual al anterior, pero el caso de prueba base es elegido por el ingeniero de pruebas componindolo con los valores
ms interesantes. Se logra cobertura 1-wise.
3.3.

Partly pair-wise

Se seleccionan los dos parmetros ms significativos y se construyen casos


de prueba con todas los posibles combinaciones de estos dos parmetros. Luego,
la batera de casos de prueba se va ampliando aadiendo un valor para cada uno
de los parmetros restantes.
3.4.

All combinations

Se generan todas las combinaciones posibles de valores de prueba mediante


el clculo del producto cartesiano de todos los conjuntos de valores interesantes
de cada parmetro.
3.5.

Anti-random

Esta estrategia, debida a Malaiya [24], se basa en que cada caso de prueba
debera seleccionarse de forma que tenga la mayor distancia con respecto a los
dems. Los parmetros y los valores interesantes se codifican en un vector binario.
Los casos de prueba se van seleccionando en funcin de su distancia de
Hamming o de su distancia cartesiana con respecto a los que se han generado
con anterioridad.
Supongamos que, para el problema del tringulo, tenemos los valores
{1,2,3}, {4,5} y {6,7} para los tres lados, que se codifican segn la Tabla 9. Anti-

59

Pruebas de sistemas de informacin

random empieza con la seleccin de un caso arbitrario. Sea el (1,4,6) este primer
caso, que corresponde a la palabra 0000; si se utiliza la distancia Hamming, el
siguiente caso ser aqul que tenga el mayor nmero diferente de bits, con lo
que se selecciona la palabra 1111, correspondiente al caso (3,5,7). El siguiente
caso ser aquel cuya suma de distancias Hamming a los dos casos seleccionados
sea mayor.
Valor

A (*)

B
C

Cdigo
1

00

01

10

11

Tabla 9. Codificacin en binario de los valores de prueba. (*) El valor 3


de A recibe dos cdigos para utilizar todas las combinaciones de los dos
bits

El trabajo de Malaiya no especifica la condicin de parada de Antirandom, y


tampoco este algoritmo garantiza la satisfaccin de ninguno de los criterios de
cobertura tradicionales (pair-wise, etc.).

4. Estrategias de generacin fuera de la clasificacin


anterior
De entre los criterios de cobertura de cdigo enumerados en el Captulo 3, es
de destacar la dificultad de conseguir valores aceptables para, por ejemplo, mutacin. Pinsese, por ejemplo, en la dificultad de encontrar valores que maten
los mutantes de una condicin tan simple como if (a<10) si esta instruccin se
encuentra a una distancia computacional considerable de la entrada del programa. La generacin de casos de prueba con algoritmos de minimizacin construye una funcin de minimizacin para cada condicin, aplicando entonces
diferentes heursticas para conseguir la cobertura, en funcin de los datos recogidos durante la ejecucin de cada caso.

60

Pruebas de sistemas de informacin

A continuacin se hace una revisin rpida de tres mtodos basados en algoritmos de minimizacin: uno basado en Bsqueda Tab y dos en algoritmos genticos, si bien existen otras posibilidades, como el uso de Simmulated Annealing o enfoques hbridos como el propuesto por [25].
4.1.

Bsqueda Tab

Daz et al. [26] proponen la utilizacin de un algoritmo basado en Bsqueda


Tab para lograr amplia cobertura de decisiones (Figura 26). La Bsqueda Tab
se basa en el algoritmo de los k-vecinos, junto al mantenimiento en memoria de
una lista tab que evita repetir la bsqueda dentro de un rea del espacio de
soluciones. Al algoritmo se le deben suministrar algunos parmetros, como la
funcin objetivo (que mide el coste de la solucin), la estrategia para seleccionar
vecinos y la memoria del algoritmo.
Generar una solucin aleatoria como solucin actual
Calcular coste de la solucin actual y almacenarlo como mejor coste
Aadir la solucin actual como nueva solucin
Aadir la nueva solucin a la lista tab
do
Calcular los vecinos candidatos
Calcular el coste de los candidatos
Almacenar el mejor candidato como nueva solucin
Aadir la nueva solucin a la lista tab
if coste de nueva solucin < mejor coste
Almacenar nueva solucin como mejor solucin
Almacenar coste de la nueva solucin como mejor coste
end_if
Almacenar nueva solucin como solucin actual
while no se alcance el criterio de parada

Figura 26. Algoritmo de bsqueda tab

Puesto que el objetivo de estos autores es alcanzar la mayor cobertura posible, utilizan un grafo que representa el flujo de control del programa, en cuyos
nodos se anota si el propio nodo ha sido alcanzado, cuntas veces lo ha sido y
cul es el mejor caso de prueba que lo ha alcanzado. Cuando no hay ramas inalcanzables, el mximo valor posible para la cobertura es el 100%, mientras que
ser desconocido en caso de que las haya. Por este motivo establecen como cri-

61

Pruebas de sistemas de informacin

terio de parada o haber alcanzado todas las ramas, o que el algoritmo haya superado un nmero de iteraciones prefijado. Adems, cada solucin se caracteriza por su conjunto de valores de entrada. El coste de una solucin, fundamental
para que el algoritmo funcione eficazmente, se calcula considerando que el mejor caso de prueba es aquel que tiene ms posibilidades de que sus vecinos permuten entre ramas o, lo que es lo mismo, aquel que alcanza el nodo con valores
lmite. Por ejemplo, si la condicin es x!=y, la funcin de coste ser |x-y| (vase
la referencia para conocer el resto de detalles de clculo de la funcin de coste).
Para calcular los vecinos candidatos, los autores se basan en que, si un caso
de prueba cubre al padre de un nodo pero no a su hijo, entonces puede encontrarse un vecino que alcance al hijo utilizando el caso que cubre al padre a partir
de la mejor solucin. A partir de sta generan 2n vecinos cercanos y 2n vecinos lejanos (donde n es el nmero de variables de entrada del programa). Los
candidatos se comprueban frente a la lista tab, rechazndose aquellos que ya
existen. En la siguiente iteracin se repite el proceso, con la diferencia de que el
nodo objetivo puede haber cambiado si alguno de los candidatos alcanz el entonces nodo objetivo.
4.2.

Generacin mediante algoritmos bacteriolgicos.

Baudry et al. [27] parten de un conjunto inicial de casos de prueba. Su algoritmo se ejecuta en varias iteraciones, en cada una de las cuales se aplican mutaciones a los casos de prueba. El algoritmo memoriza los casos de prueba que
pueden mejorar la calidad del test suite, la cual se mide mediante una funcin
de fitness.
El algoritmo dispone de cinco funciones principales:
1) Fitness del test suite, que se mide utilizando algn criterio de cobertura.
2) Fitness relativo de un caso de prueba tc: se calcula en funcin del fitness
del test suite, TS:
relFitness(TS, tc) = fitness(TS {tc}) - fitness(TS)
3) Memorizacin, que memoriza o no un caso de prueba en funcin de fitness relativo de dicho caso.

62

Pruebas de sistemas de informacin

4) Mutacin, que genera nuevos casos de prueba a partir de otros. Los casos
de prueba origen se toman aleatoriamente del test suite, si bien la probabilidad de tomar un caso u otro depende del fitness relativo de cada caso.
5) Filtrado, que va eliminando los casos que no se utilizan con el fin de preservar la memoria.

5. Ejercicios
1) Partiendo del conjunto de casos de prueba (1, 1, 1), (2, 2, 2), (3, 3, 3) y
(4,4,4) para el problema del tringulo, construya un conjunto de ms calidad
aplicando, manualmente, un algoritmo gentico. Cmo evoluciona la calidad
del conjunto al generar cada nueva poblacin?

63

Pruebas de sistemas de informacin

Captulo 6. PRUEBAS DE CAJA NEGRA


Por lo general, las pruebas de caja negra se consideran pruebas de ms alto
nivel que las de caja blanca. De hecho, se utilizan tcnicas de caja negra tanto
para realizar pruebas unitarias, como para otros niveles de prueba, como las
funcionales, de integracin, de sistema o de aceptacin [28].

1. Pruebas de componentes
En terminologa UML, un componente es una parte fsica reemplazable de
un sistema que empaqueta su implementacin, y que es conforme a un conjunto
de interfaces a las que proporciona su realizacin [29]. Esto significa, sencillamente, que el componente ofrece una serie de servicios (mtodos) a sus usuarios
a travs de una interfaz; las operaciones incluidas en la interfaz se implementan
dentro de la lgica del componente.
Un componente, por tanto, representa una unidad de construccin reutilizable, que puede ensamblarse para formar aplicaciones.
Habitualmente, el componente se percibe como una pieza de la que se conoce la interfaz que ofrece y las salidas que aporta, por lo que pueden considerarse
paradigmticos para considerarlos cajas negras.
1.1.

Uso de BIT wrappers


Edwards [30] propone la utilizacin de BIT wrappers (Built-In-Test wrap-

pers, o adaptadores construidos durante las pruebas) para la prueba de componentes. Esencialmente, un BIT wrapper es una clase que ofrece la misma interfaz que el componente para el que se ha construido. En la fase de pruebas del
componente, se ejecutan las operaciones de ste a travs del BIT wrapper, que
posee funcionalidades como la comprobacin de las precondiciones de la operacin antes de llamar a la operacin real, y la comprobacin de las postcondiciones tras su ejecucin. Adems, el BIT wrapper puede mantenerse para que capture las llamadas que los clientes hacen a las operaciones del componente
(Figura 27).

65

Pruebas de sistemas de informacin

Figura 27. Ubicacin del BIT wrapper alrededor del componente.


Figura tomada de [30]

Algunas caractersticas de los BIT wrappers son las siguientes:

Son transparentes al componente y a los posibles clientes.

La adicin o supresin de BIT wrappers slo requiere la modificacin


de las declaraciones en el cdigo de los clientes.

Se aaden nuevas capacidades de comprobacin de restricciones a las


que ya realiza el propio componente.

La violacin de las restricciones se detectan en el momento en que ocurren, de manera que se evita su propagacin a otros componentes.

Si se posee una especificacin formal del componente, el BIT wrapper


se puede generar automticamente.

Para la fase de pruebas del componente, propone el proceso que se muestra


esquemticamente en la Figura 28: el conjunto de casos de prueba contenido en
el Test suite (que se ha podido generar automticamente) se pasa a un ejecutor
de pruebas (Test driver), que prueba el componente a travs del BIT wrapper.
El resultado es, por un lado, los resultados obtenidos de la ejecucin de cada
caso de prueba y, por otro, un informe con los errores encontrados.

66

Pruebas de sistemas de informacin

Figura 28. Proceso de pruebas con BIT wappers

Tanto el BIT wrapper como el Test driver pueden generarse automticamente: para el primero es preciso disponer de una descripcin formal del componente (el autor utiliza el lenguaje Resolve, aunque podra emplearse cualquier
otro); para la generacin del segundo podran usarse generadores aleatorios, de
valores lmite, etc.
1.2.

Mutacin de interfaces

Ghosh y Matur [31] proponen aplicar ciertos operadores de mutacin a las


interfaces de componentes para la realizacin de pruebas, as como ciertos criterios de cobertura para validar las pruebas realizadas.
Los autores proponen los siguientes operadores de mutacin para CORBAIDL son los siguientes:

Reemplazar inout por out.

Reemplazar out por inout.

Intercambiar parmetros de tipos compatibles.

Jugar con un parmetro (operador twiddle): por ejemplo, sumarle


uno si es entero, aadirle un carcter si es una cadena, etc.

Poner a cero los valores numricos.

Sustituir por null.

67

Pruebas de sistemas de informacin

Los criterios de cobertura que proponen son los siguientes:

Cobertura de llamadas a mtodos de la interfaz del componente.

Cobertura de excepciones lanzadas por la interfaz del componente.

Cobertura de llamadas a mtodos y de excepciones lanzadas.

La mutacin se consigue sustituyendo la interfaz por una nueva versin,


como muestra la Figura 29.
Cliente

Interfaz

Servidor

Interfaz
mutada

Cliente

Servidor

Figura 29. Mutacin de interfaces

2. Pruebas de servicios web


Mediante los servicios web, un cliente puede ejecutar un mtodo en un
equipo remoto, transportando la llamada (hacia el servidor) y el resultado (desde el servidor al cliente) mediante protocolo http (normalmente). La idea es servir la misma funcionalidad que permiten otros sistemas de invocacin remota
de mtodos, como RMI, pero de un modo ms portable.
La portabilidad se consigue gracias a que todo el intercambio de informacin entre cliente y servidor se realiza en SOAP (Simple Object Access Protocol),
un protocolo de mensajera basado en XML: as, la llamada a la operacin consiste realmente en la transmisin de un mensaje SOAP, el resultado devuelto
tambin, etc. De este modo, el cliente puede estar construido en Java y el servidor en .NET, pero ambos conseguirn comunicarse gracias a la estructura de los
mensajes que intercambian.
Los servidores ofrecen una descripcin de sus servicios web en WSDL (Web
Services Description Language), que es una representacin en XML de la interfaz del servicio ofrecido. As, un cliente puede conocer los mtodos ofrecidos por
el servidor, sus parmetros con sus tipos, etc., simplemente consultando el correspondiente documento WSDL, que se encuentra publicado en alguna URL.

68

Pruebas de sistemas de informacin

2.1.

WSDL

Supongamos que un sistema de gestin bancario ofrece, para validar las


operaciones realizadas con tarjeta de crdito, el siguiente mtodo remoto:
public boolean validar(String numeroDeTarjeta, double importe)
Si este mtodo es accesible como un servicio web, debe estar descrito en
WSDL, por ejemplo, como se muestra en la Figura 30.
<?xml version="1.0" encoding="UTF-8" ?>
- <definitions name="VisaWS" targetNamespace="http://visa/dominio/Visa.wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://visa/dominio/Visa.wsdl"
xmlns:ns1="http://visa.dominio/IVisaWS.xsd">
- <types>
<schema targetNamespace="http://visa.dominio/IVisaWS.xsd"
xmlns="http://www.w3.org/2001/XMLSchema" xmlns:SOAPENC="http://schemas.xmlsoap.org/soap/encoding/" />
</types>
- <message name="validar0Request">
<part name="numeroDeTarjeta" type="xsd:string" />
<part name="importe" type="xsd:double" />
</message>
- <message name="validar0Response">
<part name="return" type="xsd:boolean" />
</message>
- <portType name="VisaPortType">
- <operation name="validar">
<input name="validar0Request" message="tns:validar0Request" />
<output name="validar0Response" message="tns:validar0Response" />
</operation>
</portType>
- <binding name="VisaBinding" type="tns:VisaPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
- <operation name="validar">
<soap:operation soapAction="" style="rpc" />
- <input name="validar0Request">
<soap:body use="encoded" namespace="VisaWS"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
- <output name="validar0Response">
<soap:body use="encoded" namespace="VisaWS"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>
- <service name="VisaWS">
- <port name="VisaPort" binding="tns:VisaBinding">
<soap:address location="" />
</port>
</service>
</definitions>

Figura 30. Descripcin en WSDL

De la figura anterior merece la pena destacar algunos elementos, que se


enumeran y explican en la Figura 31.

69

Pruebas de sistemas de informacin

- <message name="validar0Request">
<part name="numeroDeTarjeta"
type="xsd:string" />
<part name="importe" type="xsd:double" />
</message>

- <message name="validar0Response">
<part name="return" type="xsd:boolean" />
</message>
- <portType name="VisaPortType">
- <operation name="validar">
<input name="validar0Request"
message="tns:validar0Request" />
<output name="validar0Response"
message="tns:validar0Response" />
</operation>
</portType>

Nombre del mtodo accesible de forma


remota, nombres y tipos de los parmetros. El sufijo Request denota el formato
en que debe enviarse la solicitud al servidor. Cuando el cliente invoca el servicio,
enva un mensaje validar0Request.
Tipo del resultado devuelto por el mtodo. El sufijo Response se refiere
precisamente a que es el tipo devuelto
lo que se est representando.
Operaciones que conforman la interfaz del servicio validar, que se corresponden con los dos messages anteriores.

Figura 31. Significado de algunos elementos del WSDL mostrado en la


figura anterior

Los entornos de desarrollo recientes incluyen los add-ins necesarios para


generar la especificacin WSDL de una clase.
2.2.

Escritura de un cliente que acceda a un servicio web

El cliente que utiliza el servicio web necesita una clase que acte como proxy
entre l mismo y el servicio web ofertado por el servidor. Cuando el proxy recibe
del cliente una solicitud de llamada al servicio web, el proxy la traduce a un
mensaje SOAP, que enva al servidor; ste, entonces, lo ejecuta, y devuelve un
mensaje SOAP al proxy, que traduce el mensaje a objetos Java, .NET, etc. y entrega el resultado al cliente que efectu la peticin.
La siguiente figura muestra la relacin entre el proxy, el servicio web y la
clase que lo implementa: el servicio web (en el centro) ofrece a los clientes acceso a la operacin validar(String, Double); la operacin se encuentra realmente
implementada en la clase situada abajo (Visa), y podra incluir llamadas a otros
mtodos de otras clases, acceso a una base de datos, acceso a otros servicios
web, etc. El elemento de la izquierda (VisaWSStub) es la clase que acta de
proxy entre los clientes y el servicio web. Ntese que esta clase incluye, adems
de otras, la operacin validar(String, Double). El proxy mostrado se ha obtenido de forma automtica con un entorno de desarrollo, por lo que sus miembros
pueden variar de unos casos a otros. El atributo _endpoint representa la URL en
la que se encuentra publicado el servicio web.

70

Pruebas de sistemas de informacin

Figura 32. El proxy, el servicio web y la clase que lo implementa

La aplicacin cliente hace entonces uso del proxy para acceder al servicio
web, por ejemplo con un trozo de cdigo como el que sigue:
protected void validarDisponibilidadDeCredito(double importe) throws Exception
{
// Se intancia el proxy
VisaWSStub stub = new VisaWSStub();
// Se le dice al proxy dnde puede encontrar el servicio web
stub.setEndpoint("http://161.67.27.108:8988/soap/servlet/soaprouter");
// Se llama al mtodo ofertado por el proxy
if (!stub.validar("", new Double(5.0)).booleanValue())
throw new Exception("Operacin no admitida");
}

Figura 33. Acceso desde el cliente al servicio web a travs del proxy

2.3.

Pruebas de servicios web mediante perturbacin de datos

Offutt y Xu [32] proponen la utilizacin de perturbacin de datos para realizar las pruebas de servicios web. Los mensajes SOAP se modifican y se utilizan
como casos de prueba. La tcnica de la perturbacin de datos utiliza tres mtodos para probar los servicios web:
(1) Perturbacin de los valores de los datos.
(2) Perturbacin de la comunicacin RPC.
(3) Perturbacin de la comunicacin de datos.
En perturbacin de valores, se sustituyen los valores de los datos en los
mensajes SOAP por otros valores basndose en la tcnica de valores lmite (la
Tabla 10 muestra los valores lmite de cinco de los diecinueve tipos de datos de
SOAP).

71

Pruebas de sistemas de informacin

Tipo de dato
String

Valores lmite

Decimal, float, double

Cadena de mxima longitud, de mnima longitud, toda en maysculas, toda en minsculas


Mximo valor, mnimo valor, cero

Boolean

true, false

Tabla 10. Valores lmite para algunos tipos de datos

En perturbacin de la comunicacin RPC, la prueba se enfoca en el


uso que se hace los datos que se envan en el mensaje, distinguindose dos usos:
usos normales y usos de SQL. Los usos de SQL son aquellos en los que los datos
se utilizan para construir consultas SQL. Por ejemplo, si desde un formulario se
envan un login y una password para realizar una consulta y validar a un usuario, se pueden alterar los valores pasados con el fin de encontrar comportamientos inesperados en el servicio web (Figura 34).

<soapenv:Body>
<adminLogin soapenv:encodingStyle=>
<arg0 xsi:type=xsd:string>turing</arg0>
<arg1 xsi:type=xsd:string>enigma</arg1>
</adminLogin>
</soapenv:Body>

<soapenv:Body>
<adminLogin soapenv:encodingStyle=>
<arg0 xsi:type=xsd:string>turing OR 1=1</arg0>
<arg1 xsi:type=xsd:string>enigma OR 1=1</arg1>
</adminLogin>
</soapenv:Body>

Figura 34. Un mensaje SOAP original (izquierda) y modificado

En los usos normales, los valores se alteran aplicando algunos operadores de


mutacin. Por ejemplo, si se pasa el valor numrico n, puede sustituirse por 1/n,
n*n, etc.
En perturbacin de la comunicacin de datos, se pretende probar las
relaciones y la integridad de los datos, ya que muchos de los datos que se envan
a los servicios web incluyen, implcitamente, informacin relativa a la estructura
de la base de datos. Por ejemplo, el carrito de una tienda electrnica puede almacenar una lista de los cdigos de los productos que compra un cliente sin duplicar ninguno; puede aadirse a la lista de productos un elemento duplicado
para observar el comportamiento del sistema.

3. Pruebas de integracin con mquinas de estado en


orientacin a objetos
Como ya se ha comentado, en el contexto de la orientacin a objetos, las
pruebas de integracin pretenden asegurar que los mensajes que fluyen desde
los objetos de una clase o componente se envan y reciben en el orden adecuado
72

Pruebas de sistemas de informacin

en el objeto receptor, as como que producen en ste los cambios de estado que
se esperaban.
Gallagher et al. describen una metodologa para realizar pruebas de integracin mediante el modelado del sistema como una mquina de estados [11]. Las
mquinas de estado se utilizan con mucha frecuencia para describir el comportamiento de clases individuales. Una mquina de estados para una clase C puede describirse mediante una tupla (V, F, P, S, T), donde:

V es el conjunto de los campos de C.

F es el conjunto de las operaciones de C.

P es el conjunto de parmetros de las operaciones.

S es el conjunto finito de estados. Cada estado se describe como un


predicado sobre los valores de los campos de C.

T es un conjunto finito de transiciones entre estados. Cada transicin


t se etiqueta una tupla como la siguiente: t=(estadoOrigen, estadoDestino, operacin, guarda, accin). En sta:
o estadoOrigen y estadoDestino son elementos de S.
o operacin es la operacin que dispara la transicin, si la guarda se evala como cierta.
o guarda es un predicado sobre los campos de C y los parmetros de las operaciones de F.
o action es una serie de cmputos que se ejecutan, como consecuencia de que se dispara la transicin.

Los autores proponen el concepto de mquina de estados combinada (para


describir sistemas compuestos por varias clases) mediante la extensin de la
definicin descrita arriba: a la tupla (V, F, P, S, T) se le aade el conjunto de clases C, obteniendo (C, V, F, P, S, T). Los elementos V, F, P, S y T se redefinen, de
manera que alberguen la unin de todos los campos, operaciones, parmetros,
estados y transiciones de todas las clases que intervienen en el sistema que se
pretende someter a pruebas de integracin.
El primer paso de la metodologa es la identificacin del componente cuyas
interacciones con el resto del sistema van a ser probadas. A partir de este componente, se identifican las transiciones relevantes de ese componente, que pueden ser de entrada o de salida. Para calcular el conjunto de transiciones relevan-

73

Pruebas de sistemas de informacin

tes, se parte de las transiciones que salen del componente, y se ejecuta a continuacin un proceso iterativo por el que se van aadiendo las transiciones llamadas por las transiciones que ya estn en el conjunto.
Despus se construye un grafo de flujo a partir de la mquina de estados
combinada, en el cual se consideran:

El conjunto de transiciones relevantes.

Los estados origen o destino de las transiciones que se han identificado como relevantes.

El conjunto de guardas de transiciones relevantes.

Entonces, se est casi en condiciones de construir los casos de prueba: el


grafo de flujo incluye transiciones y estados, con los que pueden definirse criterios de cobertura, a partir de los cuales se pueden generar los casos de prueba.

4. Ejercicios
1) Explique las similitudes entre las pruebas de componentes mediante mutacin de interfaces y las pruebas de servicios web mediante perturbacin de
datos.
2) Suponga que tenemos un sistema orientado a objetos como el de la figura
siguiente, y que queremos probar el correcto funcionamiento de este sistema
ejecutando los servicios que ofrece la clase C1. Razone si tendra utilidad inyectar fallos en las clases interiores (C2 a C5) para realizar las pruebas.
C1

C2

C3

C4

C5

74

Pruebas de sistemas de informacin

Captulo 7. PRUEBAS DE ARTEFACTOS DIVERSOS


Como se mencion en el primer captulo, se aplican diferentes tcnicas de
prueba a cada tipo de producto software. En este captulo se mencionan algunas
tcnicas de prueba para artefactos distintos del cdigo fuente.

1. Testing basado en requisitos


Diversos estudios han mostrado que el coste de corregir un error crece ms
que linealmente conforme se avanza en las diversas fases del ciclo de vida. As,
si corregir un error en la fase de requisitos cuesta 1 unidad monetaria, corregir
el mismo error en la codificacin puede ser 10 veces ms costoso, y hasta 100
veces ms cuando el producto ya se encuentra en explotacin.
Un estudio citado por Mogyorodi [33] indica que el origen del 56% de los
errores de los proyectos software se encuentra en la fase de requisitos. De este
56%, aproximadamente la mitad se debe a requisitos mal redactados, ambiguos,
poco claros o directamente incorrectos, mientras que la otra mitad se debe a
requisitos que, simplemente, no se encontraban en la especificacin.
Con el fin de arrastrar el menor nmero posible de errores hacia fases posteriores del desarrollo, deben verificarse los cuatro principales atributos de calidad de los requisitos:

Complecin: los requisitos deben especificar completa y claramente


el problema.

Correccin: no debe haber ambigedad en ningn requisito. Cualquier requisito no debe tener ms que una interpretacin.

Consistencia: no debe haber requisitos contradictorios.

Factibilidad: los requisitos deben ser factibles e implementables.

La metodologa RBT [33] (Requirements-Based Testing) pretende, a partir


de una revisin inicial de los requisitos, derivar el nmero mnimo de casos de
prueba necesario para cubrir el 100% de los requisitos funcionales. RBT consta
de los siguientes 12 pasos:

75

Pruebas de sistemas de informacin

1) Validacin de los requisitos con respecto a sus objetivos. A partir


del plan del proyecto, se comparan sus objetivos (en donde se describe por qu
se desarrolla el proyecto) con los requisitos (en los que se especifican qu funcionalidades va a servir el sistema que se va a desarrollar). Si ese qu no se corresponde con el por qu, los requisitos no cumplirn los objetivos del proyecto
y ste fracasar. Pueden detectase, adems, requisitos (qus) que no encuentren
sus correspondientes por qus: estos requisitos no forman parte del alcance del
proyecto y pueden ser eliminados.
2) Descripcin de los requisitos mediante casos de uso. Al describir
los requisitos mediante casos de uso, y stos mediante escenarios, se puede
comprobar si los requisitos se encuentran satisfechos por los diferentes escenarios de los casos de uso. En caso de que no, se habr encontrado que la especificacin de requisitos est incompleta.
3) Revisin de la ambigedad. Se revisa la redaccin de los requisitos
con objeto de eliminar palabras, frases o construcciones ambiguas y conseguir
que el requisito pueda ser probado (Figura 35).
Descripcin inicial de un requisito:
Cuando el cajero automtico sea forzado, ste enviar una alerta al departamento de TIC. En el caso de que el cajero sea abierto sin llave y sin introducir el cdigo de seguridad, el cajero alertar inmediatamente al departamento TIC con objeto de que se tome la accin correspondiente.
El requisito no puede ser probado porque contiene ambigedades,
algunas de las cuales son:
1) Tipo de alerta que debe enviar el cajero al departamento TIC.
2) Qu significa que el cajero es forzado.
3) Es lo mismo que el cajero sea forzado y que es abierto sin llave y sin introducir el cdigo de seguridad?
4) Qu ocurre si se utiliza la llave y se introduce un cdigo incorrecto, o al
revs?
5) Cul es la accin correspondiente?
Figura 35. Revisin de las ambigedades en un requisito

4) Revisin de los requisitos por parte de expertos en el dominio,


de modo que se revise la correccin y complecin de los requisitos.
5) Creacin de una tabla de decisin. Los requisitos se traducen a tablas de decisin, que permiten encontrar y resolver problemas de sinonimia,
aclarar precedencias entre requisitos, explicitar informacin que permaneca
ms o menos oculta, y comentar el proceso de pruebas de integracin.

76

Pruebas de sistemas de informacin

Supongamos un sistema bancario en el que hay una funcin de retirada de efectivo en la que se hace una comprobacin del saldo de la cuenta y del crdito
concedido a dicha cuenta. La funcin conoce el importe que se desea retirar, el
saldo de la cuenta y el crdito concedido (el crdito es un nmero negativo, que
representa el saldo negativo que se autoriza alcanzar a este cliente). Las posibles
acciones son las siguientes:
Autorizar la retirada del efectivo y enviar una carta.
Autorizar la retirada del efectivo.
Suspender la cuenta y enviar una carta.
La funcin tiene los siguientes requisitos:
Si saldo-importe>=0, se autoriza la retirada de efectivo.
Si saldo-importe<0 ^ saldo-importe>=crdito, se autoriza la retirada y
se enva una carta.
Si saldo-importe<0 ^ saldo-importe<crdito, se suspende la cuenta y se
enva una carta.
Del enunciado se extraen 3 efectos:
E1: autorizar la retirada de efectivo.
E2: suspender la cuenta.
E3: enviar la carta.
Estos efectos se consiguen a partir de las siguientes causas:
C1: saldo-importe>=0.
C2: saldo-importe>=crdito.
A continuacin, se construye la tabla de decisin:
C1: saldo-importe>=0
C2: saldo-importe>=crdito
E1: autorizar retirada
E2: suspender la cuenta
E3: enviar la carta

1
0
0
0
1
1

Reglas
2 3
0 1
1 0
1 0 1 -

4
1
1
1
0
0

En la tabla de decisin, la regla 3 es infactible pues se corresponde con


causas mutuamente excluyentes (C1 y C2). Por las propiedades de reduccin de tablas de decisin, podra reducirse el nmero de reglas. Para la
funcin descrita tendramos que escribir tres casos de prueba (uno por
Figura 36. Construccin de la tabla de decisin

6) Revisin de la consistencia de la tabla de decisin, lo que permitir obtener los casos de prueba que cubran el 100% de los requisitos funcionales.
7) Revisin de los casos de prueba por parte de los autores de los
requisitos, de modo que si se encuentra algn problema con algn caso de
prueba, los requisitos asociados con el caso de prueba podrn ser corregidos y
los casos de prueba rediseados.
8) Validacin de los casos de prueba con los expertos en el dominio, con objeto de encontrar posibles problemas en los requisitos de los cuales
proceden.

77

Pruebas de sistemas de informacin

9) Revisin de los casos de prueba por parte de los desarrolladores, de modo que stos conozcan mejor los requisitos del sistema que tienen
que construir y puedan orientar la construccin hacia la superacin de estos
casos de prueba.
10) Utilizacin de casos de prueba en las revisiones del diseo.
Con esta tarea, se puede comprobar si el diseo que se est realizando satisfar
los casos de prueba y, por tanto, los requisitos. Igualmente, podra llegarse a la
conclusin de que alguno de los requisitos no sea factible.
11) Utilizacin de casos de prueba en las revisiones del cdigo.
Puesto que cada fragmento de cdigo sirve un fragmento de los requisitos, los
casos de prueba pueden utilizarse para comprobar que, efectivamente, el cdigo
se comporta como se esperaba.
12) Verificacin del cdigo contra los casos de prueba. En este ltimo paso, se construyen casos de prueba ejecutables a partir de los casos de
prueba de alto nivel. Cuando todos los casos ejecutables se ejecuten satisfactoriamente contra el cdigo, puede decirse que se ha verificado el 100% de la funcionalidad.

2. Secuencias de mtodos
En el contexto de las pruebas de sistemas orientados a objetos, Kirani y Tsai
[34] consideran la secuencia como un concepto fundamental para la prueba de
clases. Una secuencia representa el orden correcto en el que los mtodos pblicos de una clase pueden ser invocados. De acuerdo con estos autores, una de las
aplicaciones de las secuencias es la prueba de clases a partir de su especificacin
como una mquina de estados.
As, puede utilizarse la especificacin del comportamiento de una cierta clase en forma de mquina de estados para generar casos de prueba, ejecutarlos y
medir nuevos criterios de cobertura. En el ejemplo de la Figura 37, se conseguira una cobertura completa de estados con la secuencia m1.m2.m3.m4, mientras
que deberan ejecutarse otras secuencias para lograr cobertura de transiciones o
cobertura de caminos. A partir de aqu surgen con facilidad otros criterios de
cobertura, como la ejecucin de cada camino cero veces, una vez y ms de una
vez, cobertura de guardas, de acciones, etc.

78

Pruebas de sistemas de informacin

m3

s3

m3
m1
s0

m2
s1

s2

m4

m3

m4
s4

m4

Figura 37. Mquina de estados para una cierta clase

3. Especificaciones formales o semiformales


3.1.

Propuesta de Tse y Xu

Tse y Xu [35] utilizan la especificacin formal de una clase para obtener el


espacio de estados de la clase y generar casos de prueba.
De manera general, una clase puede especificarse utilizando combinadamente dos formas de representacin: una capa funcional, en la que se representan los valores abstractos de los objetos de la clase, y una capa de restricciones,
en la que se anotan la clase y sus operaciones con precondiciones, postcondiciones e invariantes.
La Figura 38 muestra las dos capas de una clase Account, que podra representar una cuenta bancaria, con un determinado lenguaje de especificacin
(aunque lo cierto es que existen muchos ms para representar lo mismo, como
se ver ms adelante en, por ejemplo, la Figura 40).

79

Pruebas de sistemas de informacin

Capa funcional de una clase


module ACCOUNT is
including MONEY .
sort AccountSort .

Capa de restricciones de la misma clase


class Account is
based on sort AccountSort .
invariant {balance(self) >= - creditLimit} .

var X : AccountSort .
var M : Money .
var N : Money .

constructor Account()
ensure {balance(result) == balance(empty)} .
method credit(M : Money)
require {M > 0} .
ensure {balance(post-self) ==
balance(creditS(pre-self, M))} .

let creditLimit = 1000 .


op empty : -> AccountSort .
op creditS : AccountSort Money -> AccountSort .

method debit(M : Money)


require {M > 0 and balance(debitS(pre-self, M)) >= creditLimit} .
ensure {balance(post-self) ==
balance(debitS(pre-self, M))} .

op balance : AccountSort -> Money .


eq balance(empty) = 0 .
eq balance(creditS(X, M)) = M + balance(X) .
op charge : AccountSort Money -> Money .
eq charge(empty, N) = 0 .
ceq charge(creditS(X, M), N) = N * 0.05
if N < 200 and balance(creditS(X, M)) < 0 .
ceq charge(creditS(X, M), N) = 10
if N >= 200 and balance(creditS(X, M)) < 0 .
ceq charge(creditS(X, M), N) = 0
if balance(creditS(X, M)) >= 0 .

method findBalance() : Money


ensure {result == balance(pre-self)
and balance(post-self) == balance(pre-self)} .
endclass

op debitS : AccountSort Money -> AccountSort .


eq debitS(empty, N) = creditS(empty, - N) .
eq debitS(creditS(X, M), N) =
creditS(X, (M - N - charge(creditS(X, M), N))) .
endmodule

Figura 38. Capas funcional y de restricciones de una clase

La capa funcional incluye la descripcin de los tipos importados (including


MONEY), el nombre del tipo (sort AccountSort), las posibles variables que se
utilicen a continuacin (var X, M, N) y un conjunto de clusulas que especifican
los resultados de las operaciones:

op representa la signatura de la operacin. Por ejemplo: op charge :


AccountSort Money -> Money indica que la operacin charge toma un
parmetro de tipo AccountSort y otro de tipo Money y que devuelve un
Money.

eq representa propiedades de las operaciones descritas mediante ecuaciones. Por ejemplo, eq balance(empty) = 0 indica que el resultado de
ejecutar la operacin balance (en ingls, saldo) sobre una cuenta
creada con la operacin empty (en ingls, vaca), es cero; eq debitS(empty, N) = creditS(empty, - N) indica que sacar N euros de una

80

Pruebas de sistemas de informacin

cuenta vaca (cuyo saldo es cero) es lo mismo que sacar los mismos N
euros a crdito.

ceq representa propiedades de las operaciones descritas mediante


ecuaciones condicionales. Por ejemplo, ceq charge(creditS(X, M), N) =
N * 0.05

if N < 200 and balance(creditS(X, M)) < 0 indica que sacar

N euros de una cuenta X de la que se han sacado a crdito M euros supone el cobro de un 5% de comisin sobre el importe sacado, si ste es
menor que 200 euros y el saldo de la cuenta es negativo.
La capa de restricciones del caso de la figura incluye, por ejemplo, una invariante que indica que el saldo de la cuenta debe ser siempre superior al crdito
concedido (invariant {balance(self) >= - creditLimit}); una postcondicin sobre
el constructor Account que denota que el saldo de una cuenta recin creada es
cero (constructor Account() ensure {balance(result) == balance(empty)}), y
una precondicin para la operacin credit(M : Money) que expresa que el importe que se saca a crdito debe ser positivo (require { M>0 }).
A partir de estas consideraciones, los autores realizan una particin del espacio de estados de la clase, obteniendo estados abstractos por cada trmino
booleano de la capa funcional. A partir, por ejemplo, de la propiedad eq balance(empty)=0 podran obtenerse los estados en que la cuenta tiene saldo negativo, saldo cero y saldo positivo. Combinando adems estos estados con la invariante de la capa de objeto (invariant {balance(self) >= - creditLimit}), se podran obtener los siguientes cinco subestados:

balance(self) < -creditLimit

inalcanzable debido a la invariante

balance(self) = -creditLimit

0> balance(self) > -creditLimit

balance(self) = 0

balance(self) > 0

Puesto que el valor de creditLimit es 1000, los estados concretos son los
siguientes (ntese la adicin de un estado inicial adicional, en el que el objeto se
encuentra antes de ser creado; igualmente podran crearse estados finales si la
clase tuviera destructores):
S0= { no creado }; S1= { b==1000 }; S2= { -1000<b<0}; S3= { b==0}; S4={ b>0}

81

Pruebas de sistemas de informacin

Obtenidos los estados, se genera el conjunto de transiciones, formadas por


una llamada a un mtodo y una posible condicin de guarda, obtenida de las
precondiciones del mtodo. De este modo, del anterior conjunto de estados y del
ejemplo de la Figura 38 se obtiene la mquina de estados mostrada en la Figura
39.
t0= Account()
t1= credit(m) {0 < m < 1000}
t2= credit(m) {m == 1000}
t3= credit(m) {1000 < m}
t4 = credit(m) {0 < m < 1000 and b + m == 0}
t5 = credit(m)
{(0 < m < 1000 and 0 < b + m) or 1000 m}
t6 = credit(m) {0 < m < 1000 and -1000 < b + m < 0}
t7 = credit(m) {0 < m}
t8 = credit(m) {0 < m}
t9 = debit(m) {1000 < m and b - m == -1000}
t10 = debit(m) {0 < m and -1000 < b - m < 0}
t11 = debit(m) {0 < m and b - m == 0}
t12 = debit(m) {0 < m and 0 < b - m}
t13 = debit(m) {0 < m < 1000}
t14 = debit(m) {m == 1000}
t15 = debit(m)
{(200 m < 990 and b - m == -990) or
(0 < m < 200 and b - 1.05 * m == -1000)}
t16 = debit(m)
{(200 m < 990 and -990 < b - m < 10) or
(0 < m < 200 and -1000 < b - 1.05 * m < 0)}
t17 = findBalance()
t18 = findBalance()
t19 = findBalance()
t20 = findBalance()

Figura 39. Mquina de estados obtenida, tomada de

La mquina de estados se procesa para generar secuencias de mtodos que


logren diferentes criterios de cobertura, como cobertura de estados, transiciones
y caminos.
3.2.

Mtodo ASTOOT

Doong y Frankl [36] utilizan especificaciones algebraicas de las clases para


la generacin y ejecucin de casos de prueba en su mtodo ASTOOT (A Set of
Tools for Object-Oriented Testing). Una especificacin algebraica consta de una
parte sintctica y otra semntica:

La sintctica incluye los nombres y signatura de las operaciones.

La semntica incluye una lista de axiomas que describen la relacin entre funciones, utilizndose en muchos casos axiomas de reescritura para esta descripcin. As, dos secuencias de operaciones S1 y S2 son equivalentes si se pueden usar los axiomas como reglas de reescritura para
transformar S1 en S2.

82

Pruebas de sistemas de informacin

La siguiente figura, tomada de , muestra la especificacin algebraica de una


cola de prioridad. De acuerdo con esta figura, la secuencia create.add(5).delete(3) es equivalente a la secuencia create.add(5), pues puede aplicarse dos veces el sexto axioma.

Figura 40. Especificacin algebraica de una cola de prioridad

Para estos autores, dos objetos O1 y O2 de clase C son observacionalmente


equivalentes si y slo si:
(1)

C es una clase primitiva (entero, real...), O1 y O2 tienen valores


idnticos.

(2)

C no es una clase primitiva y, para cualquier secuencia S de


operaciones de C que devuelven un objeto de clase C, O1.S es
observacionalmente equivalente a O2.S como objeto de clase
C.

83

Pruebas de sistemas de informacin

En otras palabras, cuando es imposible distinguir O1 de O2 usando las operaciones de C. Si se dispusiera de una cantidad de tiempo infinita para comprobar si dos objetos son observacionalmente equivalentes, podra utilizarse el siguiente procedimiento para comprobar la correccin de la clase C:

Sea U el conjunto de tuplas (S1, S2, etiqueta), donde S1 y S2 son secuencias de mensajes, y etiqueta es un texto que vale equivalente o no
equivalente.

Para cada tupla de U, enviar las secuencias S1 y S2 a O1 y O2 y comprobar si ambos objetos son observacionalmente equivalentes.

Si todas las equivalencias observacionales se comprueban de acuerdo


con las etiquetas, entonces la implementacin de C es correcta, e incorrecta en caso contrario.

La equivalencia observacional de dos objetos puede resolverse con un mtodo tipo equals; sin embargo, la finitud del tiempo para realizar las pruebas
es irresoluble, por lo que sus autores la han adaptado en la familia de herramientas ASTOOT. El componente de generacin de casos de prueba toma la
descripcin sintctica y semntica de la clase que se va a probar (Figura 40) y la
traduce a una representacin arborescente. Con esta representacin, lee una
secuencia de operaciones suministrada por el usuario y le aplica una serie de
transformaciones para obtener secuencias de operaciones equivalentes. Las
operaciones incluidas en las secuencias son simblicas, en el sentido de que carecen de parmetros reales. Por ltimo, y teniendo en cuenta la asuncin explicada ms arriba, la comprobacin de la correccin de la clase la realizan pasando valores reales a los parmetros de los mensajes contenidos en las secuencias
de cada tupla.
3.3.

Obtencin automtica de especificaciones algebraicas

Henkel y Diwan [37] han desarrollado una herramienta que obtiene de manera automtica especificaciones algebraicas a partir de clases Java. Comienzan
obteniendo una lista de secuencias de operaciones vlidas mediante llamadas
sucesivas a los constructores de la clase y a algunos de sus mtodos, pasando
valores adecuados a los parmetros de estas operaciones. Si alguna de las se-

84

Pruebas de sistemas de informacin

cuencias lanza una excepcin, se deshace la ltima operacin o se prueba con un


nuevo valor del argumento (Figura 41).

Figura 41. Generacin incremental de trminos aplicada a la clase


IntStack (Pila de enteros), tomada de

Generadas las secuencias, obtienen ecuaciones de igualdad del estilo de las


mostradas en la Figura 38 y en la Figura 40, pero que incluyen valores reales en
lugar de simblicos:

Ecuaciones de igualdad de secuencias diferentes, como por ejemplo:


pop(push(IntStack().state, 4).state).state=IntStack().state

Ecuaciones de igualdad de secuencias con constantes, como:


pop(push(IntStack().state, 4).state).retval=4

A partir de las ecuaciones se generan los axiomas, que constan de dos secuencias y una serie de variables cuantificadas. As, de la ecuacin de la izquierda, se obtiene el axioma de la derecha:
IntAdd(size(IntStack().state).retval,1).retval = s:IntStack, i:int
size(push(IntStack().state, 3).state).retval

IntAdd(size(s).retval,1).retval =
size(push(s, I).state).retval

Figura 42. Ejemplo de obtencin de un axioma a partir de una ecuacin

Muchos de los axiomas generados son redundantes, por lo que con posterioridad se detectan y se eliminan aplicando reglas de reescritura, para lo que primero deben identificarse stas de entre el conjunto de axiomas. Se considera
que un axioma es una regla de reescritura si: (1) el lado izquierdo y el derecho
tienen diferente longitud; y (2) las variables libres que aparecen en lado ms

85

Pruebas de sistemas de informacin

corto son un subconjunto de las variables libres que aparecen en el lado derecho.

4. Pruebas a partir de mquinas de estado


Las mquinas de estado han sido fuente frecuente de trabajos de investigacin en el rea de pruebas de software. Una mquina de estados es un grafo dirigido cuyos nodos representan los estados en los que puede encontrarse una
instancia, y cuyos arcos representan transiciones entre dichos estados. Las transiciones, normalmente, se disparan por la ejecucin de una operacin de la instancia.
El uso de las mquinas de estado para describir casos de prueba (Seccin 2,
pgina 78) se puede completar con la definicin de criterios de cobertura especficos para mquinas de estado. A continuacin se describen los criterios propuestos por Offutt et al. [38].
4.1.

Cobertura de transiciones

Este criterio se satisface cuando el conjunto de casos de prueba contiene casos que provocan el disparo de todas las transiciones contenidas en la mquina
de estados.
4.2.

Cobertura de predicados

Los predicados son las expresiones booleanas que etiquetan las guardas
(condiciones en las transiciones de las mquinas de estado). Formalmente, un
predicado es una expresin booleana compuesta de clusulas y cero o ms operadores booleanos. A su vez, una clusula es una expresin booleana formada
por expresiones booleanas combinadas con operadores no booleanos (por ejemplo, operadores relacionales). Por ltimo, una expresin booleana es una expresin cuyo valor puede ser true o false. Esto se ilustra en la Tabla 11.
a
b
a>b
a<b
(a>b) and (b<c)

Expresin booleana
Clusula
Predicado

Tabla 11. Expresin booelana, clusula y predicado (a, b y c son valores


booleanos que pueden valer true o false)

86

Pruebas de sistemas de informacin

La cobertura de predicados se basa en el hecho de que cada clusula debera


ser probada independientemente, como si su valor no estuviese afectado por el
resto de clusulas. En otras palabras, deben considerarse las diferentes clusulas de un predicado capaces de determinar el valor de todo el predicado:
Una clusula ci determina un predicado si un cambio en el
valor de verdad de ci cambia el valor de todo el predicado.
Un predicado es cubierto completamente por un conjunto de casos de prueba cuando se cubren todas la clusulas que lo componen. Ms formalmente:
Para cada predicado P en cada transicin y cada clusula ci
de P, un conjunto de casos de prueba T satisface el criterio de
cobertura de predicados si T incluye casos tales que cada
clusula ci en P toma los dos valores (true y false).
Supongamos que deseamos obtener casos de prueba para verificar este criterio con el predicado (A or B) and C. Para satisfacer este requisito, podemos
construir la tabla de verdad para ese predicado (Tabla 12) y tomar aquellas combinaciones de A, B y C que hagan a A true una vez y false otra, a B true una vez y
false otra, y a C true una vez y false otra: o sea, que podramos reducir el conjunto de casos a los que aparecen resaltados en la tabla.
A
0
0
0
0
1
1
1
1

B
0
0
1
1
0
0
1
1

C
0
1
0
1
0
1
0
1

A or B
0
0
1
1
1
1
1
1

(A or B) and C
0
0
0
1
0
1
0
1

Tabla 12. Tabla de verdad para (A or B) and C

4.3.

Cobertura de pares de transiciones

Este criterio se satisface cuando el conjunto de casos de prueba contiene casos de prueba que recorren, para un estado dado, todos los pares de transiciones
de entrada y salida de ese estado.
As, para la mquina de estados de la Figura 43, este criterio ser satisfecho
si el conjunto de casos de prueba contiene casos que recorran (m1, m3), (m1,
m4), (m1, m5), (m2, m3), (m2, m4) y (m2, m5).

87

Pruebas de sistemas de informacin

m3

m1

m4

S
m2
m5

Figura 43. Un fragmento de una mquina de estados

4.4.

Cobertura de secuencia completa

Este criterio se satisface cuando el conjunto de casos prueba contiene casos


que recorren los caminos (formados por transiciones) ms significativos, que
son aquellos que previamente ha seleccionado el ingeniero de pruebas.

88

Pruebas de sistemas de informacin

5. Obtencin de casos de prueba a partir de casos de uso


Basanieri et al. [39] utilizan diagramas de casos de uso y de secuencia para
derivar casos de prueba desde las etapas iniciales del desarrollo de un sistema
orientado a objetos. Tras realizar una serie de anlisis y adaptaciones de los diagramas, aplican los siguientes pasos:

Definir el conjunto de secuencias de mensajes MS a partir de los diagramas de secuencia. Cada secuencia comienza con un mensaje m sin
predecesor (habitualmente, un mensaje enviado al sistema por un actor) y el conjunto de mensajes cuya ejecucin dispara m (aquellos cuyo
inicio est en el foco de control en que termina m).

Analizar subcasos, que bsicamente consiste en construir varias secuencias a partir de las posibles instrucciones condicionales que anotan
los diagramas de secuencia.

Identificar los conjuntos de valores de prueba, que se construyen a partir de los tipos de los parmetros de los mtodos y del anlisis de los
diagramas de clases del sistema.

Seleccionar, para cada mensaje de la secuencia, las situaciones relevantes en que el mensaje puede ocurrir y, para cada valor de prueba, valores vlidos que puedan incluirse en el mensaje.

Eliminar valores contradictorios o poco significativos, para lo que los


autores sugieren utilizar clases de equivalencia.

Obtener procedimientos de prueba, que puede hacerse automticamente con los datos obtenidos en los pasos anteriores.

As, a partir del diagrama de secuencia mostrado en la Figura 44, se identifican las siguientes secuencias de mensajes:
MS_1: 1.start(), 1.1.open()
MS_2: 2.enterUserName(String)
MS_3: 3.enterPassword(String)
MS_4: 4.loginUser(),

4.1.validateuserIDPassword(String, String)
4.2.setupSecurityContext(), 4.2.1.new UserID()
4.3.closeLoginSelection()

El diagrama incluye sin embargo una instruccin condicional, por lo que la


secuencia MS_4 puede dividirse en dos:

89

Pruebas de sistemas de informacin

MS_4.1: 4.loginUser(),

4.1.validateuserIDPassword(String, String)
4.2.setupSecurityContext(), 4.2.1.new UserID()

MS_4.2: 4.loginUser(),

4.1.validateuserIDPassword(String, String)
4.3.closeLoginSelection()

Figura 44. Diagrama de secuencia de ejemplo, tomado de

6. Diseo de clases orientados a la facilidad de pruebas


Baudry et al. analizan la complejidad de diagramas de clases UML con respecto a su facilidad de prueba, con el objetivo de proponer una serie de guas de
diseo que permitan disear sistemas orientados a objeto fciles de probar o, al
menos, probables en tiempo finito. El estudio se basa fundamentalmente en
medidas de acoplamiento, que viene a ser el grado en que unos elementos dependen de otros; as, se asume que a mayor acoplamiento (tanto directo como
indirecto), mayor dificultad para probar el diseo.
Estos autores dan las siguientes definiciones:

90

Pruebas de sistemas de informacin

Relacin de uso directa: la clase A usa la clase B cuando existe una asociacin desde A hacia B, o bien cuando hay una dependencia con el estereotipo
<<usa>> desde A hacia B. Este conjunto de relaciones se llama SDU (Set of Direct Usage relationship). Ntese que una asociacin no dirigida representa
realmente dos relaciones de este conjunto.
Relacin de uso transitiva: es el conjunto formado por la clausura transitiva de SDU.
Relacin de uso transitiva real: si existe una relacin transitiva entre
las clases A, B y, adems, el cdigo fuente obtenido del diagrama de clases permite la interaccin entre dos instancias de A y de B, entonces se dice que dicha
relacin transitiva es real.
Interaccin de clases (interaccin potencial): siendo A, B dos clases,
ocurre si y slo si A Ri B y B Ri A, siendo i distinto de j. [La interaccin es potencial porque tal vez no llegue fsicamente a producirse en la ejecucin del sistema].
Interaccin entre objetos (interaccin real): siendo A, B dos clases,
ocurre si y slo si (1) A Ri B y B Ri A, siendo i distinto de j, y (2) Ri y Rj son relaciones transitivas reales. [La interaccin es real porque se produce la interaccin entre ambos objetos en la ejecucin del sistema obtenido del diseo].
El criterio de prueba propuesto es el siguiente: para cada interaccin entre clases, o bien se obtiene un caso que prueba la interaccin entre objetos, o
bien se obtiene un informe mostrando que tal interaccin no es factible.
Puesto que la tarea de producir casos de prueba o informes es imposible si el
nmero de interacciones es muy alto, es preciso obtener diseos que disminuyan el nmero de interacciones, de modo que se haga factible as la prueba
completa del diseo de clases.
Antes de someterlo al criterio de pruebas, el diseo de clases debe ser evaluado para conocer el nmero de interacciones entre clases, modificndolo si es
muy alto y tal mejora es posible, o rechazndolo directamente en otro caso. La
mejora del diseo puede lograrse reduciendo el acoplamiento o anotndolo con
restricciones que eviten la codificacin de interacciones entre objetos propensas
a error. Los autores proponen la anotacin utilizando los estereotipos <<create>> (para indicar que la clase A crea instancias de la clase B),

91

Pruebas de sistemas de informacin

<<use_consult>> (para indicar que la clase A slo utiliza mtodos tipo get de B)
y <<use_def>> (para indicar que la clase A modifica el estado de las instancias
de B). Estos estereotipos se utilizan en el proceso de construccin del Grafo de
Dependencias de Clases (en ingls Class Dependency Graph, o CDG), que representa las relaciones transitivas entre clases junto a las relaciones de herencia
e implementacin. La siguiente figura muestra algunos ejemplos sobre la obtencin del CDG, en la que aparecen algunas etiquetas aadidas a los nodos del
CDG para representar el tipo de relacin existente.

Figura 45. Algunos ejemplos de obtencin del CDG, tomada de

A partir del CDG pueden calcularse medidas como la complejidad de una


interaccin, definida en funcin de la complejidad de los diferentes caminos
por los que puede irse desde un objeto hasta otro:
complejidad (CI ) =

nbPaths

((complejidad ( P ) complejidad ( P ))
i

i =1

j >i

Ecuacin 5. Complejidad de una interaccin

La complejidad de un camino en una interaccin es necesaria para


calcular el valor de la Ecuacin 5, y se define como el productorio de la complejidad asociada a cada jerarqua cruzada por la interaccin (parmetro IH):

complejidad ( P) =

nbCrossed

complejidad ( IH , P)
i =1

Ecuacin 6. Complejidad de un camino en una interaccin

Obviamente, es preciso poder calcular la complejidad de un camino que


pasa por una jerarqua de herencia:

92

Pruebas de sistemas de informacin

complejidad ( IH , P ) =

nbDP

complejidad (dp )
i =1

Ecuacin 7. Complejidad de un camino que pasa por una jerarqua de


herencia

Por ltimo, la complejidad de un camino de descendientes es el nmero de interacciones potenciales entre las clases que hay en ese camino. El caso peor se dara cuando todas las clases estuvieran relacionadas con todas las
clases, lo que supone un valor mximo de n(n-1). De manera general, la complejidad de un camino se corresponde con la Ecuacin 8, en donde h representa
la altura del camino:

comlejidad (dp) = h (h 1)
Ecuacin 8. Complejidad de un camino de descendientes

En la siguiente figura, tomada de , la complejidad del camino que va desde


client hasta b1 pasando por la relacin de herencia de la clase d es 1+3*(3-1)+1:
1 por la relacin de uso de client con respecto a d; 3*(3-1) por el camino de descendientes de la jerarqua d, y otra vez 1 por la relacin de uso desde d22 a b1.

Ecuacin 9. Ejemplo para el clculo

7. Criterios de cobertura de pruebas para diseos UML


Andrews at al. [40] proponen varios criterios de cobertura para las pruebas
de diferentes diagramas UML.
Para diagramas de clases, proponen los siguientes:

AEM (Association-end multiplicity): dado un conjunto de pruebas T y


un modelo SM, T debe causar que se cree cada par de multiplicidades
representativo en las asociaciones de SM. As, si existe una asociacin
cuya multiplicidad es, en un extremo, p..n, debera instanciarse la aso-

93

Pruebas de sistemas de informacin

ciacin con p elementos (valor mnimo), n elementos (valor mximo) y


con uno o ms valores en el intervalo (p+1, n-1).

GN (Generalization): dado un conjunto de pruebas T y un modelo SM,


T debe conseguir que se cree cada relacin de generalizacin de SM.

CA (Class attribute): dado un conjunto de pruebas T, un modelo SM y


una clase C, T debe conseguir que se creen conjuntos de valores representativos de los diferentes atributos de la clase C. El conjunto de valores representativos se consigue en tres pasos: (1) crear valores representativos para cada atributo, para lo que pueden usarse clases de
equivalencia; (2) calcular el producto cartesiano de estos valores; (3)
eliminar los conjuntos de valores invlidos, considerando el dominio
del problema, posibles restricciones que anoten el diagrama, etc.

Para diagramas de interaccin, los criterios propuestos son:

Cobertura de condiciones: dado un conjunto de casos de prueba T y un


diagrama de interaccin D, T debe conseguir que cada condicin del
diagrama se evale a true y a false.

Cobertura completa de predicados (FP: full predicate coverage): cada


clusula de cada condicin debe evaluarse a true y a false.

Cobertura de mensajes (EML: each message on link): cada mensaje del


diagrama debe ejecutarse al menos una vez.

Cobertura de caminos (AMP: all message paths): todos los posibles


caminos de ejecucin deben ejecutarse.

Cobertura de colecciones (Coll: Collection coverage): el conjunto de


casos de prueba debe probar cada interaccin con colecciones al menos
una vez.

8. Revisiones e inspecciones de cdigo fuente


Las revisiones e inspecciones de cdigo fuente son una tcnica para la deteccin manual de errores en el cdigo . Se trabaja bajo el principio de que cuatro
ojos ven ms que dos, de tal manera que el mtodo de trabajo consistir, bsicamente, en pasar el cdigo escrito por un programador a un tercero o grupo de
terceros, que tratar de encontrar posibles errores, faltas de adecuacin al estilo
de codificacin utilizado por la organizacin, etc.

94

Pruebas de sistemas de informacin

Para ello suelen utilizarse listas de comprobacin (checklists), que enumeran defectos y en los que el revisor anota su presencia o ausencia. En puede
consultarse una lista de comprobacin de errores tpicos del lenguaje Java, entre los que se incluyen el control de overflows y underflows, restriccin adecuada del acceso a los miembros de las clases, control de apertura y cierre de ficheros, etc.

9. Ejercicios
1) Escriba casos de prueba que cumplan los criterios de cobertura mencionados en la Seccin 4 para la siguiente mquina de estados, que representa el
comportamiento de una cuenta corriente:

2) Escriba el cdigo correspondiente a la mquina de estados del ejercicio anterior. Somtalo a los casos de prueba que ha propuesto. Analice si hay algn tipo
de relacin entre la cobertura de la mquina de estados y la del cdigo fuente.

95

Pruebas de sistemas de informacin

Captulo 8. MTRICAS PARA EL PROCESO DE


PRUEBAS

En este captulo se presentan algunas mtricas importantes para mantener


bajo control el proceso de pruebas.

1. Introduccin
Como es bien sabido, existen multitud de mtricas para medir diferentes
atributos del software, como el nmero de lneas de cdigo, nmero de puntosfuncin, complejidad ciclomtica, complejidad de datos, etc., que pueden posteriormente ser utilizadas para la realizacin de predicciones sobre futuros proyectos de desarrollo o mantenimiento, asignacin de recursos. De esta forma, el
equipo de desarrollo es capaz de conocer las posibles desviaciones en el proyecto.
Esta misma filosofa puede tambin aplicarse al proceso de pruebas y, de
hecho, tambin para l se han definido algunas mtricas. Adems de las importantes medidas de cobertura, ya discutidas en captulos anteriores, algunas mtricas son las siguientes:
1) Nmero de casos de prueba.
2) Nmero de casos de prueba/LOC
3) Nmero de casos de prueba/Nmero de requisitos
4) LOC de casos de prueba/LOC
5) Nmero de asserts/LOC
6) Nmero de casos de prueba planificados, ejecutados y pasados.
7) Coste (en unidades monetarias o en tiempo) de las diferentes actividades del proceso de pruebas.
8) Nmero de defectos encontrados en la fase de pruebas.
9) Diferentes medidas de obertura.
A continuacin se revisan algunas mtricas importantes para el proceso de
pruebas.

97

Pruebas de sistemas de informacin

2. Porcentaje de deteccin de defectos


El objetivo de la fase de pruebas no es demostrar que el programa es correcto, sino encontrar los errores que haya en l, de tal manera que dudaremos de la
fiabilidad de un software en el que no se han encontrado errores.
El porcentaje de deteccin de defectos (PDD) es el cociente de dividir el nmero de defectos encontrados en la fase de pruebas por el nmero total de defectos presentes en el software. As, si el software objeto de la prueba tiene 100
defectos y encontramos 50, PDD=0,5.
El nmero total de defectos slo puede ser creciente, por lo que el PDD ser,
en todo caso, decreciente. Para estimar el nmero total de defectos es necesario
disponer de datos histricos de anteriores proyectos de desarrollo.

3. Porcentaje de defectos corregidos


El porcentaje de defectos corregidos (PDC) es el resultado de dividir el nmero de defectos corregidos entre el nmero total de defectos. As, pues,
PDCPDD.

4. Medida del retorno de la inversin (ROI)


A continuacin se reproduce un ejemplo del libro de Fewster y Graham [41].
Supongamos que el proceso de pruebas en una empresa supone 10.000
/ao, y que gracias a este proceso el PDD es del 70%. Asumamos tambin que
el coste de corregir un defecto antes de la entrega es de 100 , y de 1000 si se
corrige despus. Supongamos tambin que se introducen 1000 defectos en un
sistema de tamao grande. Puesto que PDD=70%, se habrn encontrado 700
defectos antes de la entrega, lo que supone un coste de 700x100=70.000 .
En un momento dado, la empresa puede decidir la inversin de 10.000
ms en pruebas (mediante, por ejemplo, cursos de formacin como ste, adquisicin de herramientas, etc.), con el fin de intentar elevar el PDD desde el 70%
actual hasta el 90%. Compensar la inversin realizada? Para ello calculamos
el ROI a un ao tal y como se muestra en la siguiente tabla.

98

Pruebas de sistemas de informacin

Proceso actual
10000
70%
700
70000
300

Coste del testing


PDD
Defectos encontrados en las pruebas
Coste de corregir en las pruebas
Defectos encontrados despus de las
pruebas
Coste de corregir despus de las pruebas
Coste total
Beneficio
Inversin realizada
ROI (beneficio/inversin)

300000
380000

Proceso mejorado
20000
90%
900
90000
100
100000
210000
170000
10000
1700%

Tabla 13. Clculo del ROI para un proyecto

99

Pruebas de sistemas de informacin

Captulo 9. REFERENCIAS
1.

2.

3.
4.

5.

6.

7.
8.
9.
10.
11.

12.
13.

14.
15.
16.
17.
18.

ISO/IEC, ISO/IEC 12207. International Standard. Software Life Cycle Processes. International Standard Organziation/International Electrotechnical Committee, 1995. Geneve.
Karlstrm D, Runeson P and Nordn S. A minimal test practice framework for
emerging software organizations. Software Testing, Verification and Reliability,
2005. 15(3): p. 145-166.
Giraudo G and Tonella P. Designing and conducting an empirical study on test
management automation. Empirical Software Engineering, 2003. 8(1): p. 59-81.
Runeson P, Andersson C and Hst M. Test processes in software product evolution -a qualitative survey on the state of practice. Journal of Software Maintenance and Evolution: Research and Practice, 2003. 15(1): p. 41-59.
Meudec C. ATGen: automatic test data generation using constraint logic programming and symbolic execution. Software Testing, Verification and Reliability, 2001. 11(2): p. 81-96.
Ball T, Hoffman D, Ruskey F, Webber R and White L. State generation and
automated class testing. Software Testing, Verification and Reliability, 2000.
10: p. 149-170.
Myers B. The Art of Software Testing. 1979: John wiley & Sons.
Cornett S. Code Coverage Analysis. 2004.
IEEE Standard for Software Unit Testing. Institute of Electrical and Electronics
Engineers, 1987.
Pressman RS. Ingeniera del Software, un enfoque prctico (3 Edicin). 1993:
McGraw-Hill.
Gallagher L, Offutt J and Cincotta A. Integration testing of object-oriented components using finite state machines. Software Testing, Verification and Reliability, 2006. 16.
Offutt AJ. A practical system for mutation testing: help for the common programmer. 12th International Conference on Testing Computer Software. 1995.
Offutt AJ, Rothermel G, Untch RH and Zapf C. An experimental determination
of sufficient mutant operators. ACM Transactions on Software Engineering and
Methodology, 1996. 5(2): p. 99-118.
Polo M, Piattini M and Tendero S. Integrating techniques and tools for testing
automation. Software Testing, Verification and Reliability, 2007. 17(1): p. 3-39.
Ma Y-S, Offutt J and Kwon YR. MuJava: an automated class mutation system.
Software Testing, Verification and Reliability, 2005. 15(2): p. 97-133.
Grindal M, Offutt AJ and Andler SF. Combination testing strategies: a survey.
Software Testing, Verification and Reliability, 2005. 15: p. 167-199.
Hoffman D, Strooper P and White L. Boundary values and automated component testing. Software Testing, Verification and Reliability, 1999. 9(1): p. 3-26.
Harrold M, Gupta R and Soffa M. A methodology for controlling the size of a
test suite. ACM Transactions on Software Engineering and Methodology, 1993.
2(3): p. 270-285.

101

Pruebas de sistemas de informacin

19.

Jeffrey D and Gupta N. Test suite reduction with selective redundancy. International Conference on Software Maintenance. 2005. Budapest (Hungary): IEEE
Computer Society.
20.
Tallam S and . NG. A concept analysis inspired greedy algorithm for test suite
minimization. 6th ACM SIGPLAN-SIGSOFT Workshop on Program
Analysis for Software Tools and Engineering. 2005.
21.
Heimdahl M and George D. Test-Suite Reduction for Model Based Tests: Effects
on Test Quality and Implications for Testing. 19th IEEE International Conference on Automated Software Engineering. 2004.
22.
McMaster S and Memon A. Call Stack Coverage for Test Suite Reduction. 21st
IEEE International Conference on Software Maintenance. 2005. Budapest
(Hungary).
23.
Shiba T, Tsuchiya T and Kikuno T. Using artificial life techniques to generate
test cases for combinatorial testing. 28th Annual International Computer Software and Applications Conference. 2004. Hong Kong, China: IEEE Computer
Society Press.
24.
Malaiya Y. Antirandom testing: Getting the most out of black-box testing. International Sym-posium on Software Reliability Engineering (ISSRE 95). 1995.
Toulouse, France: IEEE Computer Society Press, Los Alamitos, CA.
25.
Lapierre S, Merlo E, Savard G, Antoniol G, Fiutem R and Tonella P. Automatic
Unit Test Data Generation Using Mixed-Integer Linear Programming and Execution Trees. International Conference on Software Maintenance. 1999. Oxford,
England.
26.
Daz E, Tuya J and Blanco R. Pruebas automticas de cobertura de software
mediante una herramienta basada en Bsqueda Tab. VIII Jornadas de Ingeniera del Software y Bases de Datos. 2003. Alicante, Spain.
27.
Baudry B, Fleurey F, Jzquel J-M and Traon YL. Automatic test case optimization: a bacteriologic algorithm. IEEE Software, 2005: p. 76-82.
28.
Kanstrn T. Towards a deeper understanding of test coverage. Journal of Software Maintenance and Evolution: Research and Practice, 2008. 20(1): p. 59-76.
29.
Rumbaugh J, Jacobson I and Booch G. The Unified Modelling Language Reference Manual. Segunda edicin ed, ed. A.-W.O.T. Series. 2005: AddisonWesley.
30.
Edwards SH. A framework for practical, automated black-box testing of component-based software. Software Testing, Verification and Reliability, 2001(11): p.
97-111.
31.
Ghosh S and Mathur AP. Interface mutation. Software Testing, Verification and
Reliability, 2001(11): p. 227-247.
32.
Offutt J and Xu W. Generating Test Cases for Web Services Using Data Perturbation. Workshop on Testing, Analysis and Verification of Web Services. 2004.
Boston, Massachusetts.
33.
Mogyorodi GE. What is Requirement-Based Testing? CrossTalk: The Journal of
Defense Software Engineering, 2003(march): p. 12-15.
34.
Kirani S and Tsai WT. Method sequence specification and verification of
classes. Journal of Object-Oriented Programming, 1994. 7(6): p. 28-38.
35.
Tse T and Xu Z. Test Case Generation for Class-Level Object-Oriented Testing.
9th International Software Quality Week. 1996. San Francisco, CA.

102

Pruebas de sistemas de informacin

36.

37.

38.

39.

40.
41.

Doong RK and Frankl PG. The ASTOOT approach to testing object-oriented


programs. ACM Transactions on Software Engineering and Methodology, 1994.
3(2): p. 101-130.
Henkel J and Diwan A. Discovering Algebraic Specifications from Java Classes.
17th European Conference on Object-Oriented Programming (ECOOP). 2003:
Springer.
Offutt AJ, Liu S, Abdurazik A and Amman P. Generating test data from statebased specifications. Software Testing, Verification and Reliability, 2003(13): p.
25-53.
Basanieri F, Bertolino A and Marchetti E. The Cow_Suite Approach to Planning
and Deriving Test Suites in UML Projects. 5th International Conference on The
Unified Modeling Language. 2002: Springer-Verlag. LNCS.
Andrews A, France R and Ghosh S. Test adequacy criteria for UML design
models. Software Testing, Verification and Reliability, 2003(13): p. 95-127.
Fewster M and Graham D. Software Test Automation. 2000: Addison-Wesley.

103

También podría gustarte