Você está na página 1de 8

Problemas relativos a las pruebas

El siguiente fragmento de código es el algoritmo RSA de generación de claves.

generarClaves() {
EnteroGrande p, q;
do {
// Genera un entero de gran tamaño probablemente primo.
p = generarCandidato();
} while (!testPrimalidad(p);
do {
q = generarCandidato();
} while (!testPrimalidad(q);
EnteroGrande k1 = multiplicar(p, q);
EnteroGrande p_1 = restar(p, 1);
EnteroGrande q_1 = restar(q, 1);
EnteroGrande k2 = multiplicar(p_1, q_1);
almacenar(getIdentificador(), k1, k2);
}

Se pide:

a) Grafo de flujo, complejidad ciclomática y caminos independientes. ¿Cómo forzaría


la ejecución de un número n de iteraciones en los bucles while? 2.5 puntos

b) Cada función, como por ejemplo getIdentificador(. . . ), almacenar(. . . ), multi-


plicar(). . . es un módulo. Existen también otros módulos: codificar(. . . ); fac-
torial(. . . ), que usa a multiplicar(. . . ) y es usado por testPrimalidad(. . . ); di-
vidir(. . . ), usado por testPrimalidad(. . . ); publicar(. . . ), usado por almacenar(. . . );
multiplicar(. . . ) usa a sumar(. . . ) y, por último, el módulo restar(. . . ) usa a mul-
tiplicar(. . . ) y a sumar(. . . ). Esquema de los módulos. 0.5 puntos

c) Suponga que se desea realizar una integración ascendente pero con una mod-
ificación: los módulos testPrimalidad() y generarCandidato() por este orden,
se consideran críticos e interesa probarlos cuanto antes. ¿Cúal sería el orden
de integración de módulos? (puede ser que haya más de un orden posible). 2
puntos

Solución

1
Figura 1: Grafo de flujo

2
La complejidad ciclomática se puede calcular de tres formas:

 Número de regiones = 3
V(G) = Número de nodos predicado + 1 = 2 + 1 = 3

Enlaces - Nodos + 2 = 10 - 9 + 2 = 3

Caminos independientes. Por definición, dos caminos son independientes cuan-


do al menos un arco aparece en uno y no en otro. La complejidad ciclomática es el
número máximo de caminos independientes.

a) 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

b) 1 - 2 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9

c) 1 - 2 - 3 - 4 - 3 - 4 - 5 - 6 - 7 - 8 - 9

Para probar un bucle a veces es necesario que tenga exáctamente n iteraciones.


Esto, en general se puede conseguir de varias formas. La mejor y más usual es
manipular los datos de entrada para forzar el número de iteraciones deseado, si
esto no es posible, otra opción es cambiar el código de la función (mala opción
porque habría que hacerlo cada vez que se pasan las pruebas) o los módulos a los
que se llama (sustituyéndolos por otros). En nuestro caso, la condición de final-
ización es un test que comprueba si un número es primo. Una opción es cambiar
las funciones llamadas por generarClaves(), como son: generarCandidato() y test-
Primalidad(entero)
Para probar cuanto antes los módulos testPrimalidad y generarCandidato por
este orden y con integración ascendente, se procedería en este orden:
sumar - multiplicar - {factorial - dividir} - testPrimalidad - generarCandidato
- {[publicar - almacenar] - getIdentificador} - generarClaves
La notación que hemos empleado se debe interpretar de este modo: { módulo
A - módulo B } significa que el orden de integración es indiferente. [moduloA -
módulo B] significa que el módulo A precede al módulo B en la integración.

3
Figura 2: Esquema de módulos. En el enunciado se nos olvidó poner la relación
entre restar y módulo que lo utiliza, así como la relación de codificar con el resto
de los módulos.

En un grafo dirigido cuyos nodos están ordenados, el orden se indica con una
asignación de un número entero a cada nodo. Se dice que el grafo tiene un orden
ancestral si se cumple que para todo nodo Y descendiente del nodo Z, el entero
asignado a Y es menor que el asignado a Z. Dado el siguiente fragmento de código:

boolean tieneOrdenAncestral(Grafo grafo) {


Conjunto nodosExplorados = new Conjunto();
Nodo[] nodosSinHijos = getNodosSinHijos(grafo);
Pila nodosSinExplorar = new Pila(nodosSinHijos);

while (!nodosSinExplorar.vacio()) {
Nodo nodo = nodosSinExplorar.pop();
nodosExplorados.add(nodo);
Nodo[] descendientes = nodo.getDescendientes();
for (int i = 0; i < padres.length; i++) {
if (descendientes[i].orden() < nodo.orden()) {
return false;
}
if (!nodosExplorados.contiene(descendientes[i])) {
nodosSinExplorar.add(descendientes[i]);
}
}
}
return true;

4
}

Se pide:

a) Grafo de flujo, complejidad ciclomática, caminos independientes. 2.5 puntos

b) De una definición de caso de prueba. 0.5 puntos

c) Suponga que en este caso, definimos las entradas del caso de prueba como la
representación gráfica de un grafo, véase como ejemplo la figura 3. Caminos
críticos y casos de prueba.

Figura 3: Entrada de un caso de prueba

5
Suponga este fragmento de código en pseudocódigo:

equal-ignore-case(string s[1..n], string t[1..m]) : boolean


if n != m
return false
fi

for i:=1 to n:
if tolower(s[i] != tolower(t[i]):
return false;
fi
ffor
return true
end

Se pide:

a) Grafo de flujo, complejidad ciclomática, caminos independientes. 2.5 puntos

b) De una definición de caso de prueba. 0.5 puntos

c) Casos de prueba que recorrerían los caminos independientes. 1 punto

d) ¿Qué más pruebas serían necesarias en esta función? Con las pruebas prop-
uestas, ¿se puede garantizar la corrección al 100 %?. Razone la respuesta. 1.5
puntos

Solución

La complejidad ciclomática se puede calcular de tres formas:



 Número de regiones = 4
V(G) = Número de nodos predicado + 1 = 3 + 1 = 4

Enlaces - Nodos + 2 = 11 - 9 + 2 = 4

Caminos independientes. Por definición, dos caminos son independientes cuan-


do al menos un arco aparece en uno y no en otro. La complejidad ciclomática es el
número máximo de caminos independientes.
Caminos independientes y casos de prueba que los recorren:

a) 1 - 2 - 9: (“hola”, “h”, false)

b) 1 - 3 - 4 - 8 - 9: (null, null, false) <- En este caso, se admiten más respuestas.

6
Figura 4: Grafo de flujo

7
c) 1 - 3 - 4 - 5 - 6 - 9: (“h”, “i”, false)

d) 1 - 3 - 4 - 5 - 7 - 4 - 5 - 6 - 9: (“h”, “h”, true)

Un caso de prueba es una asignación de valores a los parámetros de entrada de


una función y las salidas esperadas para dichos valores.
Las pruebas realizadas son de caja blanca. Habría que realizar también algún
tipo de prueba de caja negra porque descubren otro tipo de errores que no descubren
las de caja blanca. En general, realizando todos los tipos de pruebas no se tiene una
garantía al 100 % de que el programa sea correcto, pero es muy probable que sí lo
sea.

Você também pode gostar