CC 1002: Introduccióna la Programación Testing y depuraciónnbaloian/cc1002/CC... · •...

Preview:

Citation preview

CC 1002: Introducción a la ProgramaciónTesting y depuración

Nelson Baloian, José A. Pino

Testing y Depuración• Verificación empírica y objetiva de la calidad de un producto

(En nuestro caso, Programas y Funciones).

• Se basa en verificar que la función cumpla y respete su contrato.

• Si bien no se puede probar con todos los datos, hay que probar con los que abarquen buena parte del universo de datos posibles.

• Por lo tanto: escoger los mas representativos, pero ¿cuáles son ?

Regla #1: El contrato limita el tipo y cantidad de datos con los que hay que probar la función.

• Tenemos una función que calcula el máximo entre 2 números (No nos importa como):

Ejemplo #1: máximo

¿Cuáles serian buenos test, de acuerdo a la Regla #1?

Regla #1: El contrato limita el tipo y cantidad de datos con los que hay que probar la función.

Ejemplo #1: máximo

¿Cuáles serian buenos test, de acuerdo a la Regla #1?

Regla #1: El contrato limita el tipo y cantidad de datos con los que hay que probar la función.

Ejemplo #1: máximo

¿Cuáles serian buenos test, de acuerdo a la Regla #1?

Regla #1: El contrato limita el tipo y cantidad de datos con los que hay que probar la función.

No respeta el contrato

Es Redundante

Testing (cont.)Regla #1: El contrato limita el tipo y cantidad de datos con los que

hay que probar la función.

Regla #2: Testear todas los casos limite, o de borde, dentro del dominio de la función.

• Recordemos la función potencia de la clase anterior:

Ejemplo #2: potencia

¿Cuáles serian buenos test, de acuerdo a la Regla #2 ?

Regla #2: Testear todos los casos limite, o de borde, dentro del dominio de la función.

Ejemplo #2: potencia

¿Cuáles serian buenos test, de acuerdo a la Regla #2 ?

Regla #2: Testear todos los casos limite, o de borde, dentro del dominio de la función.

Obviamente hay test “compuestos”, que combinan casos anteriores (por ejemplo, elevar un numero negativo a cero). Lo ideal es evaluar todas las posibles combinaciones.

Testeamos diversos tipos de datos

Testeamos casos de borde

Afirmaciones (assertions)• La forma general para las afirmaciones es:

• Assert no es una expresión, pero si la condición a su derecha:

• Cuando la condición se evalúa a True, la afirmación no hace nada y el programa puede continuar.

• Cuando la condición evalúa a False (es decir, si no se cumple), la afirmación arroja un error y el programa termina

Consideraciones• La buena metodología es escribir antes los test, con valores que

hayamos calculado antes, y luego escribir el cuerpo de la función.

• El uso de distintos operadores lógicos para assert nos ayuda a escribir mejores tests (y así abarcar la mayor cantidad posible de casos).

• El uso de más operadores lógicos no es una característica especial de la afirmación, sino que corresponde a las características de una condición, y que en ella se puede usar cualquier operador booleano, que reduzca a un resultado Verdadero o Falso (True o False).

Operadores booleanosOperador Significado

A == B A es igual a B ?A != B A es distinto de B?A > B A es mayor que B?A < B A es menor que B?

A >= B A es mayor o igual a B?A <= B A es menor o igual a B?

Expresión SignificadoA and B Verdadera si A y B son expresiones verdaderas.A or B Verdadera si A o B es una expresión verdadera.not A Verdadera si A es Falsa (niega la expresión).

Ejemplo: función aleatoria• Supongamos que tenemos una función que calcula aleatoriamente un

numero entre 1 y 10 (sin usar randint):

• Cada evaluación de la función resultara en un valor distinto!!

En este caso, la observación clave esta en que no nos importa que valor tome la función, sino el rango de valores que esta toma.

Ejemplo: función aleatoria

En este caso, la observación clave esta en que no nos importa que valor tome la función, sino el rango de valores que esta toma.

O bien: (es mas correcto)

Testing funciones booleanas

Caso Particular!• Si nuestra función retorna un tipo booleano, no es necesario indicar la

igualdad. • Ejemplo: tenemos una función que indica si un numero es par:

Son Equivalentes!

Testing con números reales

• Los números reales son infinitos, pero un computador tiene memoria finita!• No es posible representar infinitos números en un espacio finito

• Por lo tanto, los números reales son representados en el computador con aritmética de punto flotante.

• Estos números están sujetos a errores de precisión. Es decir, algunas operaciones no serán exactas. Ejemplo:

>>> 0.1 + 0.10.2

>>> 0.1 + 0.20.30000000000000004

*

* Paréntesis cultural, el como un computador maneja los float no forma parte de los contenidos directos del curso.

Testing con números reales

* Paréntesis cultural, el como un computador maneja los float no forma parte de los contenidos directos del curso.

Testing con números reales• Los errores de precisión también pueden propagarse. • Por ejemplo, consideremos dos cantidades, y , que en su

representación en un computador poseen errores de precisión y • Si multiplicamos estos valores, el error se amplifica!!

·

Esto produce que ciertas expresiones no entreguen los resultados que esperamos>>> assert (0.1+0.2) == 0.3

AssertionError...

¿Como podemos asegurarnos de que una función que use números de punto flotante esta correcta con respecto a nuestras pruebas?

Rango de aproximación• Para esto utilizamos un valor de tolerancia, o un épsilon , para

comparar dentro de un rango pequeño de error.• La idea es indicar que toleramos un pequeño error entre el resultado

esperado y el resultado de la función. Es decir:

ó

• Por simplicidad, crearemos la función cerca(x,y,eps), que calcula si dos números (o dos resultados) son similares, con una tolerancia épsilon.

Ejemplo: Distancia entre 2 puntos

• Implementemos la función distancia euclidiana, que calcula la distancia entre dos puntos dados por sus coordenadas , y

, .

Ahora… ¿Como testeamos esta función?

Ejemplo: Distancia entre 2 puntos

La última expresión lógicamente debería ser verdadera, pero fue evaluada a False por errores de precisión.

>>> d1 = distancia,(0.1, 0.2, 0.2, 0.1)0.14142135623730953

>>> d2 = distancia(1, 2, 2, 1)1.4142135623730951

>>> 10 * d1 == d2False

Consideremos lo siguiente:

Para Testear este tipo de funciones, usaremos la función cerca, definida anteriormente, de la siguiente manera:

Para cada problema, se debe escoger un épsilon adecuado.

Pre-condiciones• Volvamos al problema de calcular el máximo entre dos números:

• Podemos realizar una amplia gamma de test para usos adecuados de la función.

• Pero… ¿Que pasa si un usuario malvado insiste en utilizar la función en situaciones que no debería usarse, o que no tienen sentido lógico?

Pre-condiciones• Podemos incluir pre-condiciones en la función.

• Una pre-condición es una o mas afirmaciones (assert) que se ejecutan momentos antes de que la función realice su trabajo.

• En caso de que no se cumplan las pre-condiciones estipuladas para usar la función, esta termina su ejecución sin hacer nada.

• Hay 2 principales tipos de pre-condiciones:• Tipo: Que los datos sean del tipo de dato esperado.

int, long, float, complex, str, bool y muchos mas!• Rango: Que los datos estén dentro del rango de valores esperado.

ej: Al dividir / → sea distinto de 0.Al calcular , → sea mayor o igual a 0.

Pre-condiciones• Aplicando pre-condiciones a la función máximo:

• Queremos que el tipo de dato sea num (int o float).• No tenemos restricciones sobre el tamaño o rango en el que deben

estar los números.

Verificamos que y sean del tipo num, antes de hacer algo dentro de la función

Pre-condiciones• Con esto:

Las pre-condiciones nos ayudan a que nuestras funciones sean utilizadas en el contexto en el que las diseñamos.

Así, evitamos errores o malentendidos por el uso de la función en contextos para los cuales no fue diseñada.

Ejercicios Propuestos

• Crear la función primo(n), que indica si un numero es primo o no.• El numero n puede abarcar cualquier numero real.• Establezca las pre-condiciones y test adecuados para un

buen funcionamiento esperado.

• Crear la función saludo(nombre), que recibe un nombre como texto, y devuelve un texto con un saludo a tal nombre.• Ejemplo: saludo(“Camila”) entrega “Hola Camila!”• La función solo debe funcionar si se le entrega un texto

(str), y no ejecutarse en caso contrario.

(Jueves)

Estudiar toda la unidad 1!!

Para la próxima clase

Recommended