Laboratorio de Programación  >  Material de estudio  >  Apuntes  >  Pruebas de aceptación

Pruebas de Aceptación

José A. Mañas <jmanas@dit.upm.es>
Dept. de Ingeniería de Sistemas Telemáticos
Universidad Politécnica de Madrid
5 de febrero, 2004

1. Introducción

Se dice que un programa es aceptable cuando:
  1. hace lo que debe hacer
  2. no hace lo que no debe hacer

Un programador jamás debería entregar un programa sin haberlo probado. Quien recibe un programa de otro, jamás debería aceptarlo sin haberlo probado.

A partir de la especificación de lo que se espera de un programa, se prepara una batería de casos de prueba. La batería que prepara el programador le permite saber cuándo ha terminado. La batería que prepara quien va a recibir el programa le permite saber si puede aceptarlo o no.

Los casos de prueba se pueden escribir en papel y ejecutarlos disciplinadamente de forma manual, estrategia que solo es viable para programas pequeños. En programación profesional conviene automatizar las pruebas de forma que se pueden realizar muchas veces, tanto durante el desarrollo (hasta estar satisfechos), como durante la aceptación (para dar el programa por correcto, como si en el futuro hay que modificar el programa (para cerciorarnos de que no hemos roto nada que antes funcionaba).

2. JUnit

JUnit es un paquete Java para automatizar las pruebas de clases Java.

Se puede coger de
     http://www.junit.org

La forma más sencilla de utilizar JUnit es crear una clase pública que sea extensión de TestCase. En esta clase, cada prueba es un método cuyo nombre debe comenzar por "test...", ser público y no devolver nada (void). La clase suele incluir un constructor para inicializar variables privadas. Este es el patrón:

import junit.framework.*;

public class MisPruebas extends TestCase {
  // variables_privadas

  public MisPruebas () {
    // inicialización
  }

  public void testXXX () {
    // código que debe funcionar
  }
}

Ejemplo sencillo: pruebas de Java

package lprg.pruebas;

import junit.framework.*;

public class Tests extends TestCase {

 public Tests () { }

  public void testSumas () {
    assertEquals(4, 2+2);
    assertEquals(2, 2+0);
    assertEquals(2, 0+2);
  }

  public void testDivisiones () {
    assertEquals(1, 2/2);
    assertEquals(2, 4/2);
    assertEquals(2, 5/2);
  }

  public static void main (String[] args) {
  // ejecución por consola texto:
  // junit.textui.TestRunner.run(Tests.class);
  // ejecución en una ventana:
  junit.swingui.TestRunner.run(Tests.class);
  }
}

3. Funciones para probar

JUnit incluye una serie de métodos para probar que las cosas son como esperamos. Aunque se remite al lector a la documentación detallada del paquete, las siguientes funciones son básicas:
assertEquals (X esperado, X real) compara un resultado esperado con el resultado obtenido, determinando que la prueba pasa si son iguales, y que la prueba falla si son diferentes.
Realmente el método es una colección de métodos para una amplia variedad de tipos X.
assertFalse (boolean resultado) verifica que el resultado es FALSE
assertTrue (boolean resultado) verifica que el resultado es TRUE
assertNull (Object resultado) verifica que el resultado es "null"
assertNotNull (Object resultado) verifica que el resultado no es "null"
fail sirve para detectar que estamos en un sitio del programa donde NO deberíamos estar

Probablemente necesite la relación íntegra de métodos disponibles.

Las pruebas positivas detectan que estamos donde queremos. Por ejemplo:

  private int n= 2;

  public void testElemental () {
    // n vale 2
    // y 2+2 = 4
    assertEquals(4, n+n);
  }

Las pruebas negativas detectan que NO estamos donde NO queremos. Por ejemplo:

  private String nombre= "Ana";

  public void testElemental () {
    try {
      char c= nombre.charAt(4);
      fail("debería haber saltado una Exception");
    } catch (Exception e) {
      return;
    }
    fail("debería haber capturado una Exception");
  }

4. Limitaciones

JUnit no es útil para probar interfaces de entrada salida por consola o por pantalla gráfica.

5. Diseño de pruebas

Diseñar pruebas es un arte que ha sido objeto de estudio durante años. El alumno puede encontrar un estudio en la documentación adjunta.

No obstante, las reglas básicas son sencillas:

Así, para probar una función que divide dos números, probaremos los casos alrededor del valor singular "0":

6. Ejemplo 1: conjuntos

Se adjunta SetTest.java, una batería de pruebas para comprobar que funciona correctamente la clase java.util.HashSet como implementación de la clase java.util.Set.

La batería de pruebas está organizada en 6 casos de prueba cada uno centrado en una función de las proporcionadas por la clase. Y en cada caso de prueba se buscan los casos singulares

7. Temas avanzados

Lo dicho es suficiente para la inmensa mayoría de los casos; pero a veces se necesita controlar más detalles.

7.1. setUp()

Si nuestro fichero de pruebas incluye un método
	public void setUp () { ... }
JUnit lo llamará antes de lanzar cada uno de los casos de prueba, testXXX.

Puede ser útil cuando todos los casos de prueba requieren la misma inicialización de variables privadas y no basta con hacerlo en el constructor.

7.2. tearDown()

Si nuestro fichero de pruebas incluye un método
	public void tearDown () { ... }
JUnit lo llamará después de lanzar cada uno de los casos de prueba, testXXX.

Puede ser útil para cerrar elementos abiertos durante la prueba que pudieran quedar en un estado lamentable. Por ejemplo:

7.3. Same

A veces no basta probar que dos obketos son iguales con assertEqual() sino que nos interesa comprobar que es exactamente el mismo. Por ejemplo, si estamos probando algoritmos de almacenamiento y recuperación.

Para saber si dos objetos son el mismo o no:

  assertSame (X esperado, X real);
  assertNotSame (X esperado, X real);

8. Inglés

Se incluye un sucinto glosario de terminología inglesa relacionada con la prueba de programas. Se puede encontrar un glosario más extenso en la documentación adjunta.
acierto success
batería de pruebas test suite
caso de prueba test case
fallo failure
probar to test
prueba test
pruebas de aceptación acceptance test suite
repetición de pruebas regression testing

9. Referencias

El alumno puede encontrar prolija documentación el la dirección oficial de JUnit:
http://www.junit.org

En la Universidad de Rice, en Estados Unidos, han publicado un resumen de cómo hacer pruebas unitarias con JUnit y DrJava:

Unit Testing with JUnit in DrJava

Y siempre es interesante leer a Bruce Eckel:

Thinking in Java