Académique Documents
Professionnel Documents
Culture Documents
Jos A. Maas
8.2.2013
1 Introduccin
Se dice que un programa es aceptable cuando:
Un programador jams debera entregar un programa sin haberlo probado. Quien recibe un
programa de otro, jams debera aceptarlo sin haberlo probado.
A partir de la especificacin de lo que se espera de un programa, se prepara una batera de
casos de prueba. La batera que prepara el programador le permite saber cundo ha
terminado su trabajo. La batera 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; pero esta estrategia slo es viable para programas pequeos. En programacin
profesional conviene automatizar las pruebas de forma que se pueden realizar muchas veces,
tanto durante el desarrollo (hasta estar satisfechos), como durante la aceptacin (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 descargar de
http://sourceforge.net/projects/junit/
aunque debe decirse que viene ya instalado en los entornos de desarrollo habituales.
JUnit tiene 2 variantes principales, la llamada versin 3 y la versin 4. A continuacin se
describen ambas en paralelo, por si tiene que hacer una nueva batera o tiene que trabajar con
una antigua.
Una batera de pruebas es una clase java.
versin 3
import junit.framework.TestCase;
public class TestX
extends TestCase {
}
versin 4
import org.junit.Test;
import static junit.framework.Assert.*;
public class TestX {
}
versin 3
los casos de prueba son mtodos que
no devuelven nada void
su nombre empieza por test
no tienen argumentos ()
contiene aserciones
public void testSuma() {
assertEquals(4, 2+2);
assertEquals(2, 2+0);
assertEquals(2, 0+2);
}
versin 4
los casos de prueba son mtodos que
no devuelven nada: void
estn etiquetados como @Test
no tienen argumentos ()
contienen aserciones
@Test
public void pruebaSuma() {
assertEquals(4, 2+2);
assertEquals(2, 2+0);
assertEquals(2, 0+2);
}
assertSame(X esperado, X
real)
assertFalse (boolean
resultado)
assertTrue (boolean
resultado)
fail
4 Excepciones
4.1 Cuando la excepcin es un error
Si salta una excepcin que no se espera, debe fallar la prueba.
A modo de ejemplo, suponga que tenemos esta funcin que a veces lanza una excepcin
private int kaos()
throws Exception {
versin 4
@Test
public void pruebaKaos()
throws Exception {
assertEquals(7, kaos());
}
versin 3
public void testDivision() {
try {
assertEquals(0, 2 / 0);
fail("se esperaba Exception");
} catch (Exception e) {
// es lo esperado
}
}
versin 4
@Test(expected = ArithmeticException.class)
public void testDivision()
throws Exception {
assertEquals(0, 2 / 0);
}
5 Mtodos auxiliares
versin 3
import junit.framework.TestCase;
versin 4
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.*;
import java.util.*;
import static junit.framework.Assert.*;
}
@After
public void tearDown() {
s = null;
}
@Override
public void tearDown() {
s = null;
}
@Test
public void test0() {
assertTrue(s.isEmpty());
}
@Test
public void test1() {
assertEquals(0, s.size());
}
@Test
public void test2() {
s.add("x");
assertEquals(1, s.size());
}
}
5.1 @Before
En versin 3: setUp()
JUnit lo llamar antes de lanzar cada uno de los casos de prueba.
Puede ser til cuando todos los casos de prueba requieren la misma inicializacin de variables
privadas y no basta con hacerlo en el constructor.
5.2 @After
En versin 3: tearDown()
JUnit lo llamar despus de lanzar cada uno de los casos de prueba.
Puede ser til para cerrar elementos abiertos durante la prueba que pudieran quedar en un
estado lamentable. Por ejemplo:
ficheros
conexiones Internet
conexiones a bases de datos
...
5.3 @Ignore
Es til para excluir un test de la batera y que no se ejecute.
Viene a ser lo mismo que comentar el cdigo.
5.4 @Test(timeout=100)
JUnit activa un cronmetro. Si pasados 100ms no ha terminado la prueba, suena una alarma y
falla la prueba.
6 Diseo de pruebas
Disear pruebas es un arte que ha sido objeto de estudio durante aos.
No obstante, las reglas bsicas son sencillas:
hay que prever al menos una prueba para cada funcin del sistema
hay que elegir al menos un caso "normal" de datos
cuando los datos presentan singularidades (lmites o cambio de funcionamiento por
rango) hay que probar los datos anexos a cada lmite
As, para probar una funcin que divide dos nmeros, probaremos los casos alrededor del
valor singular "0":
7 Ingls
Se incluye un sucinto glosario de terminologa inglesa relacionado con la prueba de programas.
acierto
success
batera de pruebas
test suite
caso de prueba
test case
fallo
failure
probar
to test
prueba
test
pruebas de aceptacin
repeticin de pruebas
regression testing
8 Ejemplo: conjuntos
Se adjunta una batera de pruebas para comprobar que funciona correctamente la clase
java.util.HashSet como implementacin de la clase java.util.Set.
La batera de pruebas est organizada en 6 casos de prueba cada uno centrado en una funcin
de las proporcionadas por la clase. Y en cada caso de prueba se buscan los casos singulares
import java.util.*;
import junit.framework.*;
public class SetTest_v3 extends TestCase {
private String e1= "elemento 1";
private String e2= "elemento 2";
private String e3= "elemento 3";
private String e4= "elemento 4";
private String e5= "elemento 5";
public SetTest_v3() {
// constructor
// til si hay que inicializar variables privadas
}
public void testAdd () {
Set s= new HashSet();
assertEquals(0, s.size());
assertTrue(s.add(e1));
assertEquals(1, s.size());
assertTrue(s.add(e2));
assertEquals(2, s.size());
assertFalse(s.add(e1));
assertEquals(2, s.size());
}
public void testRemove () {
Set s= new HashSet();
s.add(e1);
s.add(e2);
s.add(e3);
assertEquals(3, s.size());
assertTrue(s.remove(e2));
assertEquals(2, s.size());
assertFalse(s.remove(e2));
assertEquals(2, s.size());
assertTrue(s.remove(e1));
assertEquals(1, s.size());
assertTrue(s.remove(e3));
assertEquals(0, s.size());
}
public void testClear () {
Set s= new HashSet();
s.add(e1);
s.add(e2);
s.add(e3);
assertEquals(3, s.size());
s.clear();
assertEquals(0, s.size());
}
public void testIsEmpty () {
{
"elemento
"elemento
"elemento
"elemento
"elemento
1";
2";
3";
4";
5";
public SetTest_v4() {
// constructor
// til si hay que inicializar variables privadas
}
@Test
public void testAdd() {
Set s = new HashSet();
assertEquals(0, s.size());
assertTrue(s.add(e1));
assertEquals(1, s.size());
assertTrue(s.add(e2));
assertEquals(2, s.size());
assertFalse(s.add(e1));
assertEquals(2, s.size());
}
@Test
public void testRemove() {
Set s = new HashSet();
s.add(e1);
s.add(e2);
s.add(e3);
assertEquals(3, s.size());
assertTrue(s.remove(e2));
assertEquals(2, s.size());
assertFalse(s.remove(e2));
assertEquals(2, s.size());
assertTrue(s.remove(e1));
assertEquals(1, s.size());
assertTrue(s.remove(e3));
assertEquals(0, s.size());
}
@Test
public void testClear() {
Set s = new HashSet();
s.add(e1);
s.add(e2);
s.add(e3);
assertEquals(3, s.size());
s.clear();
assertEquals(0, s.size());
}
@Test
public void testIsEmpty() {
Set s = new HashSet();
assertTrue(s.isEmpty());
s.add(e1);
s.add(e2);
s.add(e3);
assertFalse(s.isEmpty());
s.remove(e3);
assertFalse(s.isEmpty());
s.clear();
assertTrue(s.isEmpty());
}
@Test
public void testContains() {
Set s = new HashSet();
s.add(e1);
s.add(e2);
s.add(e3);
assertTrue(s.contains(e1));
assertTrue(s.contains(e2));
assertTrue(s.contains(e3));
assertFalse(s.contains(e4));
s.add(e2);
assertTrue(s.contains(e1));
assertTrue(s.contains(e2));
assertTrue(s.contains(e3));
assertFalse(s.contains(e4));
}
@Test
public void testEquals() {
Set s1 = new HashSet();
s1.add(e1);
s1.add(e2);
s1.add(e3);
Set s2 = new HashSet();
assertFalse(s1.equals(s2));
s2.add(e1);
assertFalse(s1.equals(s2));
s2.add(e2);
assertFalse(s1.equals(s2));
s2.add(e3);
assertTrue(s1.equals(s2));
assertTrue(s2.equals(s1));
s2.add(e4);
assertFalse(s1.equals(s2));
assertFalse(s2.equals(s1));
}
}