Sei sulla pagina 1di 125

Fundamentos de Ingeniería del Software

PRUEBAS
Vicente García Díaz
garciavicente@uniovi.es

Vicente García Díaz


César Fernández Acebal
Juan Manuel Cueva Lovelle
Escuela de Ingeniería Informática
Universidad de Oviedo
Curso 2010-2011
Algunos problemas famosos
2

 F-16 (1986)
 Therac-25 (1985-1987)
 Misil Patriot (1991)
 Ariadne 5 (1996)
 Mars Climate Orbiter (1999)
 Multidata Software (2001)
Ubicación general
3

 Son necesarias
 ¿Por qué hacer pruebas?
 Desarrollos en cascada o iterativos…
Revisión

Inicio
Análisis Diseño Codificación Pruebas
operación

 Pruebas vs otras etapas de desarrollo


 Software más complejo y crítico
 Costes ocasionados por los fallos muy altos
1/3 defecto
error
Conceptos básicos fallo
4

 Un del programador ocasiona un , el


cual produce un
 Error es una acción humana equivocada
 Defecto es una definición incorrecta en un software
 Fallo es la incapacidad de un sistema para realizar las
funciones especificadas en los requisitos
 No es lo mismo verificar que validar
 Verificar es determinar si se está construyendo un
producto correctamente
 Validar es determinar si se está construyendo el
producto correcto
2/3
Conceptos básicos
5

 Prueba
 Es un proceso crítico en el que un software o uno de sus
componentes se ejecuta en circunstancias previamente
planificadas con el objetivo básico de encontrar errores
 Los resultados se observan, se guardan y se evalúan

 Ciclo de prueba
 Es una actividad compuesta:
 Formar una idea de los resultados aceptables para
determinados valores de entrada
 Se ejecuta el software dándole los valores determinados en
unas condiciones específicas
 Se observan los resultados
 Se comparan los resultados con la idea inicial
3/3
Conceptos básicos
6

 Caso de prueba
 Es un escenario concreto de una prueba:
 Identificador
 Componente a probar
 Condiciones de entrada
 Datos de entrada
 Salida esperada
Id Condiciones de entrada Entrada Salida esperada
1 La base de datos está cargada 1 1,323
2 La base de datos está cargada 1,5 1,984
3 La base de datos está cargada 0,3 0,396

 ¿Cuántos casos de prueba son suficientes?


 Modelos
Objetivos de las pruebas
7

 Verificar y validar el software

 Descubrir defectos no detectados con


anterioridad

 Encontrar defectos con poco esfuerzo y tiempo

 Encontrar defectos con una alta probabilidad


Características de las pruebas
8

 Son siempre necesarias y críticas


 Pueden llegar a ocupar incluso el 30-40 % del tiempo
 Suelen suponer un coste del 30-50 % de un software
confiable
 El principio de Pareto es aplicable
 Son críticas para garantizar la calidad del software
 Sólo pueden demostrar la existencia de defectos
 No pueden ser completas
 Pueden planificarse con mucha antelación
 Son más efectivas si las dirige un equipo
independiente
Lo que deberían y no deberían hacer
9

 Deberían:
 Probar si el software no hace lo que debe hacer
 Probar si el software hace lo que no debe hacer
 Realizarse de forma independiente respecto a otras
 Estar muy bien documentadas

 No deberían:
 Ser redundantes
 Ser demasiado complejas
 Dar por supuesto que un software no tendrá defectos
Falsos mitos sobre pruebas
10

 Los desarrolladores de un módulo no deberían


probar dicho módulo

 El software no debería estar expuesto a personas


que puedan utilizarlo de forma mal intencionada

 Las personas que realizan las pruebas únicamente


trabajan en la etapa de pruebas
Esquema básico del proceso
11

Plan de pruebas Casos de prueba


Planificar Diseñar Ejecutar

Información del proyecto Resultados

Fallos encontrados
Desarrollo Depurar Evaluar

Resultados esperados
Informes
Analizar

[Piattini et al., 96]


Planificación de la prueba
12

 Identificación
 Enfoque
 Informe de incidencias
 Criterio de suspensión
 Productos a entregar
 Tareas a realizar
 Necesidades ambientales
 Responsabilidades
 Personal necesario
 Calendario
 Riesgos
Diseño de la prueba
13

 Criterios utilizados para obtener los casos de prueba


 Casos de prueba organizados
 Unidad, Integración, Sistema, …
 Resultado esperado
 Requisitos que se están probando
 Datos de prueba
 Criterios de terminación
 Un nº de defectos por unidad de tiempo de la prueba inferior a un valor
determinado
 Un nº de defectos esperado
 Un % de cobertura determinado
 Fin de tiempo o recursos
 Se ejecutaron todas las pruebas
Depuración del software
14

 Lo que se hace cuando un caso de prueba tiene éxito


 Fases de la depuración
 Localizar el defecto

 Corregir el defecto

 Técnicas más utilizadas para localizar el defecto


 Fuerza bruta

 Rastreo hacia atrás

 Eliminación de causas
Espacio conceptual
15

Prueba

* 1..n
Caso de prueba Componente Corrección

* *

Controlador

Resguardo

* *

* * * *
Fallo Estado erróneo Defecto

[Bruegge and Dutoit, 04]


Taxonomía de gestión de defectos
16

Manejo de
defectos

Evitación de Detección de Tolerancia a


defectos defectos defectos

Gestión de la Transacciones Manejo de


Metodología
configuración atómicas excepciones

Revisión

Pruebas Depuración

Pruebas Pruebas de
...
unitarias integración
[Bruegge and Dutoit, 04]
Estándares relacionados con pruebas
17

 IEEE 730  asegurar la calidad del software


 IEEE 829  documentación de las pruebas
 IEEE 830  especificaciones de los requisitos de sistemas
 IEEE 1008  pruebas unitarias
 IEEE 1012  verificación y validación del software
 IEEE 1028  inspecciones en software
 IEEE 1044  clasificación de las anomalías software
 IEEE 1061  métricas sobre calidad del software
 IEEE 12207  proceso del ciclo de vida del software y de los datos
 BS 7925-1  vocabulario de términos utilizados en las pruebas
 BS 7925-2  pruebas de componentes software
 ISO/IEC 29119  todo el ciclo de pruebas. Pretende sustituir a
otros como IEEE 829, IEEE 1008, BS 7925-1, BS 7925-2
Tipos principales de pruebas
18 desarrollador cliente usuario

Pruebas unitarias Pruebas de usabilidad

Pruebas de integración

Pruebas de sistema

Pruebas de implantación
Pruebas alfa y beta
Pruebas de aceptación
TÉCNICAS DE PRUEBAS
20 Pruebas de caja negra
Principales preocupaciones
Funcionalidad
Entradas
Salidas entrada salida
funcionalidad
1/7
Criterios de cobertura
Particiones / Clases de equivalencia
21

 Modelos (criterios)
 Consiste en reducir el número de casos de prueba:
 ¿Cómo?
 Dividiéndolos en conjuntos de datos equivalentes
 Dos fases
1. Identificar clases de equivalencia
 Es un conjunto de datos de entrada equivalentes
 Clases de equivalencia válidas  valores esperados
 Clases de equivalencia no válidas  valores no esperados
 Se obtienen de las especificaciones de entrada
2. Identificar casos de prueba
2/7
Criterios de cobertura
Particiones de equivalencia
22

 1- Identificar clases de equivalencia


 Habrá que crear una tabla enumerando cada clase

Especificación de entrada Clases de equivalencia Clases de equivalencia no


válidas válidas
3/7
Criterios de cobertura
Particiones de equivalencia
23

 1- Identificar clases de equivalencia


 Un valor numérico único
 Ejemplo: El año tiene que ser 2005
 Válida: 2005
 No válida 1: “año < 2005”
 No válida 2: “año > 2005”
 Rango de valores numéricos
 Ejemplo: Una cadena de texto tiene entre 10 y 15 letras
 Válida: “entre 10 y 15 letras”
 No válida 1: “< 10 letras”
 No válida 2: “> 15 letras”
4/7
Criterios de cobertura
Particiones de equivalencia
24

 1- Identificar clases de equivalencia


 Un valor único no numérico
 Ejemplo: El color tiene que ser rojo
 Válida: “color rojo”
 No válida: “otro color”
 Conjunto de valores
 Ejemplo: La profesión puede ser camionero, piloto o albañil
 Válida: “profesión camionero, piloto o albañil”
 No válida: “otra profesión”
 Sin embargo, si el programa los tratara de forma diferente…
 Habría que crear una clase válida por cada profesión
5/7
Criterios de cobertura
Particiones de equivalencia
25

 1- Identificar clases de equivalencia

 ¿Y las entradas múltiples?


 Hay que realizar el producto cartesiano

[http://www.uv.mx/jfernandez/]
6/7
Criterios de cobertura
Particiones de equivalencia
26

 2- Identificar casos de prueba


 Pasos:
 Cubrir absolutamente todas las clases de equivalencia
 Para las clases de equivalencia válidas
 Un caso de prueba  tantas clases de equivalencia como sea
posible
 Para las clases de equivalencia no válidas
 Un caso de prueba  una clase de equivalencia
 Ejemplo: números de teléfono
 Dos clases de equivalencia no válidas:
 “El número móvil no empieza por +34”
 “Después del código del país no hay 9 cifras”
 Si se cubrieran con un mismo caso de prueba el usuario podría
introducir como entrada:
 -40 677 00 00 00 000000
 Podrían enmascararse errores no controlados…
7/7
Criterios de cobertura
Particiones de equivalencia
27

 2- Identificar casos de prueba


 Habrá que crear una tabla con los casos de prueba

Caso de prueba Clases de equivalencia Resultado


cubiertas
1/3
Criterios de cobertura
Particiones de equivalencia. Ejemplo
28

 La idea es crear pruebas de caja negra para el


reconocimiento de identificadores de un lenguaje de
programación
 Especificación de entrada:
 Los identificadores tienen entre 2 y 10 caracteres
 El lenguaje distingue entre minúsculas y mayúsculas
 Se podrán utilizar letras, dígitos y guiones bajos
 Todos los identificadores tienen que empezar por una letra
 No se pueden utilizar palabras reservadas del lenguaje
como identificadores
2/3
Criterios de cobertura
Particiones de equivalencia. Ejemplo
29

Especificación de entrada Clases de equivalencia Clases de equivalencia no


válidas válidas
Entre 2 y 10 caracteres 1- 2 <= car <= 10 2- car < 2
3- car > 10
Letras, dígitos y guiones 4- identificadores 5- un identificador con
bajos formados por letras, caracteres que no
dígitos y guiones sean letras, dígitos o
guiones
Empieza por letra 6- el primer carácter 7- el primer carácter no
tiene que ser una es una letra
letra
No utilizar palabras 8- el identificador no 9- el identificador es
reservadas puede ser una una de las palabras
palabra reservada del reservadas del
lenguaje lenguaje
Sensible a mayúsculas 10- identificador válido 11- referenciar a un
identificador
intercambiando
alguna letra
mayúsculas /
minúsculas
Especificación de entrada Clases de equivalencia Clases de equivalencia no
3/3 válidas válidas
Entre 2 y 10 caracteres 1- 2 <= car <= 10 2- car < 2
Criterios de cobert. Letras, dígitos y guiones 4- identificadores
3- car > 10
5- un identificador con
Particiones de equivalencia. Ejemplo bajos formados por letras,
dígitos y guiones
caracteres que no
sean letras, dígitos o
guiones
30 Empieza por letra 6- el primer carácter 7- el primer carácter no
tiene que ser una es una letra
letra
No utilizar palabras 8- el identificador no 9- el identificador es
reservadas puede ser una una de las palabras
palabra reservada del reservadas del
lenguaje lenguaje
Sensible a mayúsculas 10- identificador válido 11- referenciar a un
identificador
intercambiando
alguna letra
mayúsculas /
minúsculas

Caso de prueba Clases de equivalencia Resultado


(identificador) cubiertas
Estado-1 1, 4, 6, 8, 10 El identificador es aceptado
por el sistema
A 2 Aparece un mensaje de error
Identificadorlargo 3 Aparece un mensaje de error
dinero€ 5 Aparece un mensaje de error
1dinero 7 Aparece un mensaje de error
String 9 Aparece un mensaje de error
ESTADO-1 11 Aparece un mensaje de error
1/2
Criterios de cobertura
Análisis de valores límite
31

 ¿Qué son los valores límite?


 Son aquellos que están en los márgenes de las clases
de equivalencia

 Los casos de prueba que exploran los valores


límites producen mejores resultados

 Entonces hay que:


 Seleccionar casos de prueba en los extremos

 Fijarse también en las especificaciones de salida


2/2
Criterios de cobertura
Análisis de valores límite
32

 ¿Cómo diseñar los casos de prueba?

Especificación para ENTRADA o SALIDA Criterio para obtener casos de prueba


Valor numérico único - Caso para el valor numérico
- Caso para el valor justo por encima
- Caso para el valor justo por debajo
Rango de valores numéricos - Caso para el valor máximo del rango
- Caso para el valor mínimo del rango
- Caso para el valor justo por encima
- Caso para el valor justo por debajo
Estructuras de datos con elementos - Caso para el primer elemento de la
estructura
- Caso para el último elemento de la
estructura
Especificación de entrada Clases de equivalencia Clases de equivalencia no

Criterios de cobert. Entre 2 y 10 caracteres


válidas
1- 2 <= car <= 10
válidas
2- car < 2
3- car > 10
Análisis de valores límite. Ejemplo Letras, dígitos y guiones 4- identificadores 5- un identificador con
bajos formados por letras, caracteres que no
dígitos y guiones sean letras, dígitos o
33 guiones
Empieza por letra 6- el primer carácter 7- el primer carácter no
tiene que ser una es una letra
letra
No utilizar palabras 8- el identificador no 9- el identificador es
reservadas puede ser una una de las palabras

Especificación de entrada palabra reservada del


lenguaje
reservadas del
lenguaje
(un rango de valores) Sensible a mayúsculas 10- identificador válido 11- referenciar a un
identificador
intercambiando
alguna letra
mayúsculas /
minúsculas

Caso de prueba Valor límite estudiado Resultado


(identificador)
Identifi10 Caso para el valor máximo del El identificador es aceptado
rango por el sistema
K2 Caso para el valor mínimo del El identificador es aceptado
rango por el sistema
Identific10 Caso para el valor justo por Aparece un mensaje de error
encima
K Caso para el valor justo por Aparece un mensaje de error
debajo
1/3
Criterios de cobertura
Grafo Causa – Efecto
34

 Sirve para explorar combinaciones en los valores


de entrada
 Transforma el lenguaje natural a lenguaje formal
 Entradas  causas

 Salidas  efectos

c e c e c1 e c1 e
c2 c2
Si c  e Si !c  e
OR AND
2/3
Criterios de cobertura
Grafo Causa – Efecto
35

 Ejemplo
 “Se quiere sacar dinero de un cajero”
 Causas (condiciones a cumplir)
 1- La tarjeta es válida
 2- La clave de usuario es correcta
 3- Se pasa el nº máximo
 4- Hay dinero disponible
 Efectos
 50- Sale el dinero
 51- Rechaza la tarjeta
 52- Pregunta otra clave
 53- Rechaza la operación
3/3
Criterios de cobertura
Grafo Causa – Efecto
36

 Ejemplo
 Tabla de decisión
Cuidado, es un OR
Causas Regla 1 Regla 2 Regla 3 Regla 4
1 La tarjeta es válida NO SI SI -
2 Clave correcta - SI NO -
3 Sobrepasa el nº máximo - - NO SI
4 Hay dinero disponible - SI - NO
Efectos Regla 1 Regla 2 Regla 3 Regla 4
50 Sale el dinero NO SI NO NO
51 Rechaza la tarjeta SI NO NO NO
52 Pregunta otra clave NO NO SI NO
53 Rechaza operac. NO NO NO SI

 Casos de prueba
 Una por cada columna
1/6
Criterios de cobertura
Matrices ortogonales
37

 Selecciona un subconjunto de casos de prueba


 ¿Cuándo se debe utilizar?
 Cuando hay demasiados casos de prueba

 Cuando no hay tiempo

 ¿Qué son?
 Matrices en las que si se selecciona 2 columnas
cualesquiera, en dichas columnas estarán todas las
combinaciones posibles de pares, sin repetirse
ninguna
 Estudios empíricos
2/6
Criterios de cobertura
Matrices ortogonales
38
 Proceso
1. Identificar las variables
2. Determinar el nº de opciones de cada variable
3. Encontrar una matriz ortogonal adecuada
4. Adaptar el problema a la matriz ortogonal
5. Crear casos de prueba

 Ejemplo [www.parquesoft.com, GSQA-TecnicasPruebasFuncionales.ppt]


“Un sitio Web debe operar correctamente con diferentes navegadores,
usando diferentes plugins, sobre diferentes sistemas operativos
en el cliente y utilizando diferentes servidores de aplicaciones”

 Navegadores: IE 8, Firefox 3.6, Google Chrome


 Plugins: Real Player, Media Player, ninguno
 Servidores de aplicaciones: IIS, Apache, JBoss
 Sistemas operativos: Windows Vista, Windows 7, Linux

 Combinaciones: 3 x 3 x 3 x 3 = 81
3/6
Criterios de cobertura
Matrices ortogonales
39

 1- Identificar las variables


 Navegadores, plugins, servidores de aplicaciones y
sistemas operativos

 2- Determinar el nº de opciones de cada variable


 Navegadores  3
 Plugins  3
 Servidores de aplicaciones  3
 Sistemas operativos  3

Combinaciones totales  3 x 3 x 3 x 3 = 81
4/6
Criterios de cobertura
Matrices ortogonales
40

 3- Encontrar una matriz ortogonal adecuada


 Nº de variables  4  4 columnas
 Nº de posibilidades de cada columna  3

 L9(34)  Sólo hay que contemplar 9 posibilidades

1 2 3 4
1 1 1 1 1
2 1 2 2 2
3 1 3 3 3
4 2 1 2 3
5 2 2 3 1
6 2 3 1 2
7 3 1 3 2
8 3 2 1 3
9 3 3 2 1
5/6
Criterios de cobertura
Matrices ortogonales
Navegadores
41
1 IE 8

 4- Adaptar el problema a la matriz 2 Firefox 3.6


3 Google Chrome
Plugins:

 5- Crear casos de prueba 1 Real Player


2 Media Player
3 Ninguno.
1 2 3 4 Servidores de aplicaciones:
1 1 1 1 1 1 IIS
2 1 2 2 2 2 Apache
3 1 3 3 3 3 JBoss
4 2 1 2 3 Sistemas operativos:
5 2 2 3 1
1 Windows Vista
6 2 3 1 2
7 3 1 3 2 2 Windows 7
8 3 2 1 3 3 Linux
9 3 3 2 1

Navegador Plugin Servidor SO


1 IE 8 Real Player IIS Windows Vista
2 IE 8 Media Player Apache Windows 7
3 IE 8 Ninguno JBoss Linux
4 Firefox 3.6 Real Player Apache Linux
5 Firefox 3.6 Media Player JBoss Windows Vista
6 Firefox 3.6 Ninguno IIS Windows 7
7 Google Chrome Real Player JBoss Windows 7
8 Google Chrome Media Player IIS Linux
9 Google Chrome Ninguno Apache Windows Vista
6/6
Criterios de cobertura
Matrices ortogonales
42

 No todas las combinaciones dadas por la matriz tienen


que ser válidas
 Otros ejemplos de matrices ortogonales
 L4(23)  En lugar de 8 pruebas, se hacen 4
 L8(2441)  En lugar de 64, se hacen 8
 L18(3661)  En lugar de 4374, se hacen 18

A medida que aumentan los factores, la ganancia es mucho mayor…

 A veces no existe una matriz perfecta, pero se puede


seleccionar una un poco más grande
Criterios de cobertura
Enfoque aleatorio
43

 Utilizado generalmente cuando no hay más


tiempo
 Se simula la entrada de datos
 Se pueden utilizar modelos estadísticos
 Es menos eficiente que las pruebas directas pero…
 Hay que considerar el tiempo que supone hacer un
generador aleatorio de entradas al programa y el
tiempo que supone hacer las pruebas no aleatorias
 Una vez desarrollado el generador aleatorio, la
máquina puede hacer pruebas todo el día…
44 Pruebas de caja blanca
Principales preocupaciones
Ramificaciones del código
Manejo de recursos del sistema
Manejo de errores entrada salida
Trabajo como se espera

-Caja negra y caja blanca


Análisis de la cobertura de código
45

 Es el proceso de:
 Encontrar fragmentos del software no ejecutados

 Crear casos de prueba adicionales

 Determinar un valor cuantitativo de la cobertura

 NO es necesario cubrir siempre todo el código

 NO mide la calidad del producto software


Criterios de cobertura
Sentencias
46

 Ejemplos de cobertura
 ajuste(1, 10, 0)
 ajuste(1, 11, 15)
Criterios de cobertura
Decisiones
47

Decisiones vs Sentencias

decisión edad ¿trabaja? ¿hijos? caso de prueba ¿cumple?


IF (1) <30 FALSE TRUE 1- (20, FALSE, TRUE) SI
IF (1) <30 FALSE FALSE 2- (20, FALSE, FALSE) NO
IF (2) * FALSE 2- (20, FALSE, FALSE) SI
IF (2) FALSE TRUE 3- (40, FALSE, TRUE) NO
IF (3) >60 y <70 4- (65, FALSE, TRUE) SI
IF (3) <=60 o >=70 5- (70, FALSE, FALSE) NO
Criterios de cobertura
Condiciones
48

Condiciones vs Decisiones
Condiciones vs Sentencias

decisión edad ¿trabaja? ¿hijos? caso de prueba


IF (1) <30 TRUE FALSE 1- (20, TRUE, FALSE)
IF (1) >=30 FALSE TRUE 2- (40, FALSE, TRUE)
IF (2) TRUE FALSE 1- (20, TRUE, FALSE)
IF (2) FALSE TRUE 2- (40, FALSE, TRUE)
IF (3) >60 3- (65, FALSE, FALSE)
IF (3) <70 3- (65, FALSE, FALSE)
IF (3) <=60 1- (20, TRUE, FALSE)
IF (3) >=70 4- (70, FALSE, FALSE)
Criterios de cobertura
Decisiones / condiciones
49

decisión edad ¿trabaja? ¿hijos? caso de prueba ¿cumple?


IF (1) <30 FALSE TRUE 1- (20, FALSE, TRUE) SI
IF (1) >=30 TRUE FALSE 2- (40, TRUE, FALSE) NO
IF (2) TRUE FALSE 2- (40, TRUE, FALSE) SI
IF (2) FALSE TRUE 3- (40, FALSE, TRUE) NO
IF (3) >60 4- (65, FALSE, FALSE) SI
IF (3) <70 4- (65, FALSE, FALSE) SI
IF (3) <=60 2- (40, TRUE, FALSE) NO
IF (3) >=70 5- (70, FALSE, FALSE) NO
Criterios de cobertura
Condiciones múltiples
50

decisión edad ¿trabaja? ¿hijos? caso de prueba


IF (1) <30 TRUE TRUE 1- (20, TRUE, TRUE)
IF (1) <30 TRUE FALSE 2- (20, TRUE, FALSE)
IF (1) <30 FALSE TRUE 3- (20, FALSE, TRUE)
IF (1) <30 FALSE FALSE 4- (20, FALSE, FALSE)
IF (1) >=30 TRUE TRUE 5- (65, TRUE, TRUE)
IF (1) >=30 TRUE FALSE 6- (65, TRUE, FALSE)
IF (1) >=30 FALSE TRUE 7- (70, FALSE, TRUE)
IF (1) >=30 FALSE FALSE 8- (50, FALSE, FALSE)
IF (2) TRUE TRUE 5- (65, TRUE, TRUE)
IF (2) TRUE FALSE 6- (65, TRUE, FALSE)
IF (2) FALSE TRUE 7- (70, FALSE, TRUE)
IF (2) FALSE FALSE 8- (50, FALSE, FALSE)
IF (3) >60 y < 70 6- (65, TRUE, FALSE)
IF (3) >60 y >= 70 7- (70, FALSE, TRUE)
IF (3) <= 60 y <70 8- (50, FALSE, FALSE)
IF (3) <= 60 y >= 70 no hay opción
1/12
Criterios de cobertura
Caminos
51

 Un criterio muy utilizado


 Camino
 Secuencia de pasos, desde el inicial hasta la final

 Camino de prueba
 Camino que atraviesa como máximo una vez el
interior de cada bucle que encuentra a su paso*
 Camino linealmente independiente
 Camino de prueba que introduce por lo menos un
nuevo paso respecto a otros
 Si el procedimiento lo dibujáramos como una grafo, se
correspondería con dibujar una nueva arista que no haya sido
recorrida anteriormente por otro camino
2/12
Criterios de cobertura
Caminos
52

 Fases para realizar el criterio


1. Identificar nodos

2. Dibujar grafo

3. Calcular la complejidad ciclomática


 Cuantifica la complejidad lógica

4. Determinar el conjunto de caminos linealmente


independientes

5. Crear casos de prueba


3/12
Criterios de cobertura
Caminos
53

Nodos. Sentencias  1- Identificar nodos


de código agrupadas
 ¿Cuántos nodos?
Nodos predicado. 3
Nodos surgidos de
cada condición de 1
una decisión
4
2 5
7
6
8
9
10
11
12
4/12
Criterios de cobertura
Caminos
54

 2- Dibujar grafo
Aristas. Líneas que
unen dos nodos
IF-ELSE
Regiones. Áreas
delimitadas por
false
aristas y nodos true

secuencia
5/12
Criterios de cobertura
Caminos
55

 2- Dibujar grafo

WHILE DO-WHILE

true false
true

false
6/12
Criterios de cobertura
Caminos
56

 2- Dibujar grafo

SWITCH IF múltiple

m
false true
low high
medium true
n
false
7/12
Criterios de cobertura
Caminos
57

 2- Dibujar grafo 1
2 false
6
3
4 7 8
false
5
9 10
true
false
11
12
8/12
Criterios de cobertura
Caminos
58

 3- Calcular la complejidad ciclomática


 V(G) = A – N + 2
 A  Nº de aristas del grafo
 N  Nº de nodos del grafo

 V(G) = R
 R  Nº de regiones cerradas del grafo

 V(G) = C + 1
 C  Nº de nodos de condición

Complejidad ciclomática Evaluación del riesgo


de 1 a 10 sin riesgo
de 11 a 20 riesgo moderado
de 21 a 50 alto riesgo
50 o más muy alto riesgo
9/12
Criterios de cobertura
Caminos
59

 3- Calcular la complejidad ciclomática


 V(G) = A – N + 2 = 18 – 12 + 2 = 8

 V(G) = R = 7 + la región externa = 8

 V(G) = C + 1 = 7 + 1 = 8

R1
R3
R2
R4

R7
R5
R8 R6

 Número de pruebas a realizar


10/12
Criterios de cobertura
Caminos
60

 4- Determinar el conjunto de caminos


independientes
 Heurísticos
 Elegir un camino principal (el más corto hasta el final)
 Identificar un segundo camino
 Añadiendo alguna arista nueva
 …pero tratando que sea el camino en el que menos se añaden
 Seguir identificando caminos hasta que no haya más
posibilidades
11/12
Criterios de cobertura
Caminos
61

 4- Determinar el conjunto de caminos


independientes
1. 1  2  3  4  5  12
2. 1  2  6  7  9  12
3. 1  2  3  6  7  9  12
4. 1  2  3  4  6  7  9  12
5. 1  2  6  8  9  12
6. 1  2  6  7  8  9  12
7. 1  2  6  7  9  10  12
8. 1  2  6  7  9  10  11  12
12/12
Criterios de cobertura
Caminos
62

 5- Crear casos de prueba


1. 1  2  3  4  5  12
Camino 1  beca(20, FALSE, TRUE)
2. 1  2  6  7  9  12
Camino 2  beca(40, FALSE, TRUE)
3. 1  2  3  6  7  9  12
Camino 3  no es posible
4. 1  2  3  4  6  7  9  12
Camino 4  no es posible
5. 1  2  6  8  9  12
Camino 5  beca(40, TRUE, TRUE)
6. 1  2  6  7  8  9  12
Camino 6  beca(40, FALSE, FALSE)
7. 1  2  6  7  9  10  12
Camino 7  beca(100, FALSE, TRUE)
8. 1  2  6  7  9  10  11  12
Camino 8  beca(65, FALSE, TRUE)
1/4
Criterios de cobertura
Bucles
63

 Los bucles son clave en la mayoría de los


algoritmos

 Requieren un tratamiento especial

 Instrucciones típicas
 For
 While
 Do While
2/4
Criterios de cobertura
Bucles
64

 Bucles simples
 Reglas
 No ejecutar el bucle ninguna vez
 Ejecutarlo una vez
 Ejecutarlo dos veces
 Ejecutarlo m veces, con m < n
 Ejecutarlo n-1, n y n+1 veces
3/4
Criterios de cobertura
Bucles
65

 Bucles anidados
 Reglas
 Comenzar en el bucle más interno
 Realizar pruebas de bucle simple
 Bucles externos  valores mínimos
 Ir al siguiente nivel
 Realizar pruebas de bucle simple
 Bucles externos  valores mínimos
 Bucles internos  valores típicos
4/4
Criterios de cobertura
Bucles
66

 Bucles concatenados
 Reglas
 Si son independientes
 Igual que bucles simples
 Si no son independientes
 Igual que bucles anidados

¿Bucles no estructurados?
Otros criterios de cobertura
67

 Métodos

 Hilos

 Relacionales

 Arrays
Criterios de cobertura
Basados en el flujo de datos
68

 Los programas son algo más que flujos de control


 También tienen datos
 Categorías de datos
 d  defined, created, initialized
 k  killed, undefined, released
 u  used
 c  used in a calculation
 p  used in a predicate
 Tipos de prueba
 Estática*  Identifica anomalías
 Dinámica  Ejecuta el código, similar a las pruebas de
flujo de control
 ¿Por qué no es suficiente con la versión estática?
1/6
Criterios de cobertura
Basados en el flujo de datos. Análisis estático
69

 Posibles combinaciones entre pares


Símbolos Qué ocurre Válido o no válido
˜d Definir directamente No hay problema
du Definir – Usar No hay problema
dk Definir – Eliminar Problema potencial
˜u Usar directamente Problema potencial
ud Usar – Definir No hay problema. Se usa y luego se redefine
uk Usar – Eliminar No hay problema
˜k Eliminar directamente Problema potencial
ku Eliminar – Usar Problema potencial
kd Eliminar – Definir No hay problema
dd Definir – Definir Problema potencial. Se define dos veces seguidas
uu Usar – Usar No hay problema
kk Eliminar – Eliminar Problema potencial
d˜ Definir y no más Problema potencial
u˜ Usar y no más No hay problema
k˜ Eliminar y no más No hay problema
 Entornos de desarrollo
2/6
Criterios de cobertura
Basados en el flujo de datos. Análisis estático
70

[ftp.ncsu.edu/pub/tech/2006/TR-2006-22.pdf /]
3/6
Criterios de cobertura
Basados en el flujo de datos. Análisis estático
71
4/6
Criterios de cobertura
Basados en el flujo de datos. Análisis estático
72
5/6
Criterios de cobertura
Basados en el flujo de datos. Análisis estático
73

Símbolos Qué ocurre Válido o no válido


dk Definir – Eliminar Problema potencial
˜u Usar directamente Problema potencial
˜k Eliminar directamente Problema potencial
ku Eliminar – Usar Problema potencial
dd Definir – Definir Problema potencial
kk Eliminar – Eliminar Problema potencial
d˜ Definir y no más Problema potencial

Símbolos Pasos Conclusión


dd 1-2-3 Sospechoso
Símbolos Qué ocurre Válido o no válido
6/6 dk Definir – Eliminar Problema potencial

Criterios de cobertura ˜u
˜k
ku
dd
Usar directamente
Eliminar directamente
Eliminar – Usar
Definir – Definir
Problema potencial
Problema potencial
Problema potencial
Problema potencial
Basados en el flujo de datos. Análisis estático kk Eliminar – Eliminar Problema potencial
d˜ Definir y no más Problema potencial
74
1/3
Criterios de cobertura
Basados en el flujo de datos. Análisis dinámico
75

 Estrategias (criterios de cobertura)


 All-definition (AD)
 All-p-uses (APU) Caminos

 All-c-uses (ACU)
ADUP
 All-p-uses / Some-c-uses (APU+C)
 All-c-uses / Some-p-uses (ACU+P) AU
 All-uses (AU)
ACU+P APU+C
 All-du paths (ADUP)

ACU AD APU

Decisiones

Sentencias
2/3
Criterios de cobertura
Basados en el flujo de datos. Análisis dinámico
76 Estrategia Variable Bill
AD 1-2-10
3-4-5-6
6-7
8-10
9-10
APU 1-2-3-4-5-6-7
3-4-5-6-7
6-7
ACU 1-2-10
3-4-5-6
3-4-5-9
3-4-10
6-7-8
6-7-10
8-10
9-10
APU+C (APU)+
8-10
9-10
ACU+P (ACU)
AU 3-4-5-6
6-7
6-7-8
8-10
3-4-5-9
ADUP (APU) +
(ACU)+
(AU)
3/3
Criterios de cobertura
Basados en el flujo de datos. Análisis dinámico
77 Estrategia Variable Usage
AD 0-1-2
APU 0-1-2
0-1-2-3-4
0-1-2-3-4-5
ACU 0-1-2-3-4-5-6
0-1-2-3-4-5-9
APU+C (APU)
ACU+P (ACU)
AU 0-1-2
0-1-2-3-4
0-1-2-3-4-5
0-1-2-3-4-5-6
0-1-2-3-4-5-9
ADUP (APU) +
(ACU)+
(AU)

…y ahora sólo faltaría hacer un caso de prueba para cada camino


Criterios de cobertura
Conjetura de errores
78

 Diferencia respecto a los anteriores criterios


 Ponerse en la “piel” del desarrollador y del usuario
 1- Crear una lista con errores comunes
 Cálculos
 Manejo de colecciones de datos
 Manejo de ficheros
 Permisos de los usuarios
 Usabilidad
 Interfaces para otros sistemas
 Uniones y comparaciones de datos
 Búsquedas de datos
 2- Crear los casos de prueba
79 Pruebas de caja gris
Principales preocupaciones
Registros
Información saliente
Residuos entrada salida
TIPOS DE PRUEBAS
Pruebas progresivas y regresivas
81

 Pruebas progresivas
 Realización de pruebas para tratar de encontrar
errores en partes nuevas de un software

 Pruebas regresivas
 Repetición selectiva de pruebas para estudiar
efectos adversos cuando se introducen cambios
 Probabilidad de introducir errores 50-80%
Pruebas unitarias
82

 Objetivo
 Probar un módulo software de manera independiente
 Técnica
 Caja blanca
 Caja negra
 Software para realizar este tipo de pruebas
 JUnit, NUnit, …
 Un módulo
 Es un bloque básico de construcción
 Tiene una función independiente
 Puede ser probado por separado
 No suele tener más de 500 líneas de código
Pruebas unitarias
Algunos problemas que pueden detectar…
83

1. Precedencia aritmética incorrecta


2. Cálculos incorrectos
3. Flujos de control no adecuados
4. Inicializaciones incorrectas
5. Falta de precisión
6. Representación incorrecta de una expresión
7. Interfaces de entrada / salida
8. Estructuras de datos incorrectas
9. Tratamiento de errores equivocado
Pruebas de integración
84

 Objetivo
 Verificar el correcto ensamblaje de los módulos
 Asegurando que interactúan correctamente
 Regresión

 Técnica
 Caja negra

 Estrategias principales
 No incremental

 Incremental
Pruebas de integración
Algunos problemas que pueden detectar…
85

1. Problemas de configuración
2. Problemas en métodos
3. Llamadas a métodos equivocados
4. Fallos en los parámetros
5. Mal uso de bases de datos y de ficheros
6. Fallos en la integridad de los datos
7. Fallos con polimorfismo
8. Problemas de memoria
9. Conflictos entre componentes
10. Mal uso de los recursos (memoria, disco, …)
1/2
Pruebas de integración
Estrategia incremental ascendente
86

Módulo principal
1

2 3

7 8
4 5 11
9
6 12
10

Módulos de bajo nivel


2/2
Pruebas de integración
Estrategia incremental ascendente
87

2 3

Controlador 1 Controlador 2 Controlador 3

7 8
4 5 11
9

6 12
10
Pruebas de integración
Estrategia incremental descendente
88

Resguardo 1 Resguardo 2

2 3

7 8
4 5 11
9
6 12
10
Pruebas de integración
Integración ascendente VS integración descendente
89

 Ventaja de la integración descendente


 Se prueba primero el módulo principal

 Ventaja de la integración ascendente


 No se necesitan resguardos
 Los resguardos son más complejos que los controladores

 Integración mixta
Pruebas de sistema
90

 Objetivo
 Comprobar la integración del sistema visto desde el
punto de vista global
 Técnica
 Caja negra

 Idealmente las hace un equipo


independiente
 Se basan en la especificación de

requisitos
1/6
Pruebas de sistema
Diferentes pruebas
91

 Funcionales
 Consiste en probar al sistema como un todo
 Se utiliza el software ya integrado
 Se basan principalmente en los casos de uso
 Generación de los casos de prueba
 Se toma un caso de uso por su camino típico y se generan los
casos de prueba para pasarlo
 Lo mismo para otros caminos alternativos exitosos
 Lo mismo para los caminos que terminen en fracaso
 Se crean otros casos de prueba para situaciones imprevistas
 Ausencia de algún recurso
 Imposibilidad de acceder a recursos
 Equivocaciones de los usuarios
 Situaciones de medio ambiente
2/6
Pruebas de sistema
Diferentes pruebas
92

 Funcionales
 Ejemplo de caso de uso para guiar las pruebas funcionales
“Un usuario introduce su identificador y su clave y podría entrar
en el sistema”

Mejor así:

“Un usuario introduce su identificador y su clave y entra en el


sistema. Si el usuario no es el correcto, aparecerá un mensaje
advirtiendo que el usuario no está en el sistema. Si el usuario es
correcto pero la clave no es correcta, aparecerá un mensaje
indicando que la clave no es correcta”.

 ¿Cuántos casos de prueba podrían realizarse con este caso


de uso?
3/6
Pruebas de sistema
Diferentes pruebas
93

 Humo
 Comprobar si el software funciona de manera
preliminar y directa
 Carga
 Observar el comportamiento bajo una cantidad de
peticiones esperada
 Seguridad
 Asegurar que la aplicación es segura de acuerdo con
sus necesidades
4/6
Pruebas de sistema
Diferentes pruebas
94

 Rendimiento
 Asegurar que el software cumple con los requisitos de
rendimiento de acuerdo con las especificaciones
 Recursos
 Asegurar que el software no utiliza más recursos de
los requeridos (por ejemplo memoria RAM,
procesador, disco duro, etc.)
 Configuración
 Comprobar que el software funciona correctamente
con otras configuraciones software / hardware
5/6
Pruebas de sistema
Diferentes pruebas
95

 Compatibilidad
 Asegurar que los requisitos de compatibilidad hacia
atrás se cumplen y si los métodos de actualización
funcionan
 Instalación
 Determinar si la instalación y desinstalación del
software funciona correctamente en todos los casos
 Recuperación
 Determinar si el software cumple con los requisitos de
recuperación ante fallos inesperados
6/6
Pruebas de sistema
Diferentes pruebas
96

 Disponibilidad / Servicio
 Comprobar que las condiciones de disponibilidad son las
adecuadas
 Estrés
 Identificar las condiciones máximas en las que el software
fallará en procesarlas dentro de un periodo de tiempo
determinado
 Localización
 Probar que una aplicación funciona después de traducirla a otra
¿cultura?
 Otros tipos de prueba de sistema
 Homologación
 Interoperabilidad
 Solidez
Pruebas de implantación
97

 Objetivo
 Comprobar la correcta instalación en el entorno
objetivo
 Técnica
 Caja negra

 Aspectos a tener en cuenta


 Recuperación

 Seguridad

 Rendimiento

 Comunicaciones
Pruebas de aceptación
98

 Objetivo
 Validar que un sistema cumple con lo esperado
 Permitir que el cliente acepte el sistema
 desde todos los puntos de vista
 contrato

 Técnica
 Caja negra

 Lo ideal es que el cliente sea quien aporta los


casos de prueba
 Recomendable hacerlas en el entorno objetivo
Pruebas de usabilidad
99

 Objetivo
 Encontrar problemas en las interfaces de usuario
 Técnica
 Caja negra
 Suelen realizarse muy pronto en el ciclo de desarrollo
 Aspectos a tener en cuenta
 Accesibilidad
 Calidad de respuesta
 Eficiencia
 Comprensibilidad
 Métricas
 Exactitud
 Tiempo
 Recuerdo
 Respuesta emocional
Pruebas Alfa y Beta
100

 Se emplean cuando el software no se realiza para un


cliente determinado
 Alfa
 Personas que adoptan el rol de usuario final
 Pertenecen a la organización que desarrolló el software
 Beta
 Subconjunto seleccionado (o no) de los usuarios reales
 No pertenecen a la organización
 La motivación es importante
 ¿Regresivas o progresivas?
 Alfa vs Beta
 ¿Qué problema tienen las pruebas Beta?
HERRAMIENTAS
JUnit http://www.junit.org/
102

 Es el estándar de facto para pruebas unitarias


 También hay NUnit, CppUnit, PyUnit, …

 Muy extendidas
 Eclipse, Netbeans, …

 Ciclo de vida

Preparar Ejecutar Evaluar Limpiar


Casos de prueba
103

 Es la unidad mínima de trabajo de JUnit


 Extiende junit.framework.TestCase
 public void testNAME() CONSEJO: Poner las pruebas en
 public void setUp() una carpeta diferente a la del
 public void tearDown() código pero en el mismo paquete
que la clase a probar. Así se
podrá acceder a métodos y
atributos protected
Casos de prueba a partir de JUnit 4
104

 A partir de JUnit 4 se soportan anotaciones


 No hace falta extender ninguna clase
 No hace falta poner nombres fijos a los métodos
Anotaciones
105

 Permiten probar cualquier clase (POJO, Plain Old Java Object)


Anotación Parámetros Empleo
@After Ninguno Método que se ejecuta después de cada método
de prueba
@AfterClass Ninguno Método que se ejecuta después de todos los
métodos @Test y de todos los @After
@Before Ninguno Método que se ejecuta antes de cada método de
prueba
@BeforeClass Ninguno Método que se ejecuta antes de todos los
métodos @Test y de todos los @Before
@Ignore Un String opcional Método para temporalmente decirle a JUnit que
ignore un método de prueba
@Parameters Ninguno Método que devuelve una colección de objetos.
Éstos a su vez son pasados al constructor
@RunWith Una Class Método que sirve para especificar cambios
respecto a qué tipo de ejecución se llevará a
cabo
@SuiteClasses Un array de Class Método que sirve para especificar, mediante una
anotación, los TestCases que se van a probar
en una agrupación de prueba (TestSuite)
@Test expected (opcional) Método de pruebas. expected sirve para
timeout (opcional) especificar una excepción esperada. timeout
sirve para especificar el tiempo (en ms) máximo
permitido de ejecución

 Garantías de orden
Asserts
106

 Un Assert es una Afirmación que hace alguien


Afirmación Para qué sirve
assertNull(Object x) Valida si x es null
assertNotNull(Object x) Valida si x no es null
assertTrue(boolean x) Valida si x es true
assertFalse(boolean x) Valida si x es false
assertEquals(Object x, Object y) Valida si x e y son iguales. Utiliza el método de Java
equals(Object obj1, Object obj2)
assertSame(Object x, Object y) Valida si x e y son iguales. Utiliza el operador ==
assertNotSame(Object x, Object y) Valida si x e y no son iguales. Utiliza el operador ==
fail() Falla un test de manera programática

 Si se valida la afirmación  el método de test pasa la prueba


 Con que sólo una de las afirmaciones no se cumpla  el
método de test NO pasa la prueba
Ejemplo de uso de Asserts
107

Botón Derecho  Run As  JUnit Test


Conjuntos de pruebas (SuiteCase)
108

 Es una colección de casos de prueba (TestCase)


 Sirve para clasificarlos
EasyMock http://easymock.org/
109

 ¿Qué es un Mock Object?


 Es un objeto que sirve para emular el comportamiento de otro

 ¿Dónde viene bien?

 Ciclo de vida

Crear Grabar Reproducir Verificar

 Tipos de objetos Mock


 Regular  si se espera y no se llama o si se llama sin esperarse

 Nice  si se espera y no se llama

 Strict  si se espera y no se llama o si se llama sin esperarse.


Importa el orden
Crear objetos Mock
110

 Creación de objetos Mock directa


 Los objetos Mock y su validación son independientes

 EasyMock.createMock(myInterface.class)
 EasyMock.createNiceMock(myInterface.class)
 EasyMock.createStrictMock(myInterface.class)
 Creación de objetos Mock mediante un control
 Los objetos Mock están relacionados a través del control
Grabar el comportamiento en objetos Mock
111
 Métodos que devuelven void

 Métodos que no devuelven void


.atLeastOnce()

.times(int min, int max)

.anyTimes()

 Métodos que lanzan excepciones


Reproducir y validar el
comportamiento en objetos Mock
112
 Falta, reproducir el comportamiento grabado y validar que todos los métodos
se han llamado las veces oportunas

Preparación para reproducir

Reproducciones

Validación

 ¿Qué pasa si..


 Hacemos una llamada más al método sumar? Y al restar?
 Si utilizamos createNiceMock y hacemos una llamada más al método sumar?
 Si utilizamos createNiceMock y quitamos la llamada al método restar?
 Si utilizamos createStrictMock?
CodeCover http://www.codecover.org/
113

 Cobertura de código

aplicación Java en Eclipse

aspecto de la aplicación en
funcionamiento
114
Uso de la herramienta
2- seleccionar las clases a
1- activar CodeCover estudiar

3- ejecutar la aplicación con CodeCover

 Varias formas de trabajo


Métricas de CodeCover
115

1. Statement Coverage
2. Branch Coverage
3. Term Coverage
4. Loop Coverage
5. Question mark operator (?) Coverage
6. Synchronized Coverage
1/3
Informes generados
116
2/3
Informes generados
117
3/3
Informes generados
118
JMeter http://jakarta.apache.org/jmeter/
119

 Pruebas de carga, de estrés, de rendimiento


 Diferentes protocolos
 Plan de Test
 Se pueden ir añadiendo elementos de forma jerárquica
 Elementos
 Thread groups
 Timers
 Listeners
 Target Web Page
Otras herramientas
120

 xUnit (NUnit, CUnit, CppUnit, PHPUnit, PyUnit, SUnit)


 DbUnit, HttpUnit, EJB3Unit, JUnitPerf, NoUnit
 TestNG, Cactus
 SilkTest, Selenium, Fitnesse, Fest
 JCrasher, Eclat, Symstra, TestGen4J
 JTest, CodePro
 JDepend, CheckStyle
 Cobertura, Jester, Emma, Jumble, Clover
 jMock, jMockit
 Dumbster
 Findbugs, JLint
 JProfiler
 JBench
Casos prácticos
121

 Clases de equivalencia y valores límite. Se ha creado un subsistema que


comprueba si un identificador es correcto. Un identificador tiene las
siguientes características:
 Entre 4 y 20 caracteres
 Letras válidas (a-z, A-Z)
 Dígitos válidos (2-8)
 Caracteres especiales válidos: % y –
 Como mínimo tendrá 2 letras (mínimo 1 en mayúsculas), 1 carácter especial y 1 dígito
 El primer y el último carácter son letras
 No emplea las palabras reservadas del lenguaje
Se pide crear casos de prueba adecuados para el sistema.
 Matrices ortogonales. Se ha creado un software que admite como entrada
4 parámetros (PAR1, PAR2, PAR3, y PAR4). El software se ejecuta de la
siguiente forma: >> run.exe PAR1 PAR2 PAR3 PAR4. PAR1 puede
tener como valores “a” “b” o “c”, PAR2 puede tener como valores “c”, “d” o
“f”, PAR3 puede tener como valores “g”, “h”, “i”, y PAR4 puede tener
como valores “j”, “k”, o simplemente estar vacio. Se pide crear casos de
prueba adecuados para el sistema.
Casos prácticos
122

 Grafo causa - efecto. Se ha creado un software que admite como


entrada un único parámetro (PAR1). El software se ejecuta de la
siguiente forma: >> run.exe PAR1. PAR1 es un identificador de un
libro que está formado por lo siguiente:
 Un primer bloque, que es una C (de comedia), una A (de acción), o una T (de
técnico)
 Un segundo bloque, es un número del 0 al 99999, referenciando al libro
 Ejemplos: C239, A0, T9911

Si el identificador es correcto, entonces se muestra el libro. Si el primer


bloque no es correcto, entonces se muestra un mensaje indicando que
el código no ha sido correcto. Si el segundo bloque no es correcto,
entonces se muestra un mensaje indicando que el número no ha sido
correcto
Se pide crear casos de prueba adecuados para el sistema
Casos prácticos
123

 En función del código anterior, crear casos de prueba para lo siguiente:


 Cobertura de caminos
 Cobertura de sentencias, decisiones, condiciones, decisiones-condiciones,
condiciones múltiple
 Cobertura del flujo de datos
Casos prácticos
124

 En función del código, crear


casos de prueba para lo
siguiente:
 Cobertura de caminos
 Cobertura de sentencias,
decisiones, condiciones,
decisiones-condiciones,
condiciones múltiple
 Cobertura del flujo de datos
Bibliografía
125

Potrebbero piacerti anche