Proceso unificado

Realización de pruebas

El objetivo de esta practica es comprender cómo se realizan pruebas unitarias de manera automática utilizando el framework JUnit.

JUnit

JUnit es un framework orientado a la realización de pruebas unitarias en Java. La idea en JUnit es crear una clase de prueba por cada clase que queramos probar. Esta clase de prueba se encarga de:
  1. Instanciar clase a probar
  2. Preparar el caso de prueba (fixture)
  3. Invocar metodos sobre clase a probar
  4. Verificar que los metodos entregan una salida adecuada con respecto a una entrada particular.
Una clase de pruebas hereda siempre de la clase TestCase y contiene un conjunto de metodos que corresponden a las pruebas que se van a realizar. En general, por cada metodo de la clase que queramos probar, vamos a tener un metodo en la clase de prueba. El metodo de la clase de prueba tiene el mismo nombre que el de la clase probada pero con el prefijo test. También hay que notar que se recomienda que las clases de prueba se pongan en package con el mismo nombre pero que inicie por test.

Por ejemplo:

Clase a probar Clase de prueba
package ejemplo;

public class Entero
{
    int m_valor;
   
    public void setValor(int valor)
    {
        m_valor = valor;
    }

    public int getValor()
    {
        return m_valor;
    }

    public int suma(Entero otro)
    {
       m_valor = m_valor+otro.getValor();
       return m_valor;
    }
}
package test.ejemplo;

import ejemplo.Entero;

import junit.framework.*;

public class EnteroTest extends TestCase
{
   private Entero m_entero;

   /**
    * Inicialización de la prueba
   */
   protected void setUp() throws Exception
   {
      m_entero = new Entero();
      m_entero.setValor(5);
   }

   /**
    * Prueba de setValor
   */
   public void testSetValor()
   {
      m_entero.setValor(8);
      assertEquals(m_entero.getValor(),8);
   }

   /**
    * Prueba de getValor
   */
   public void testGetValor()
   {
      assertEquals(m_entero.getValor(),5);
   }

   /**
    * Prueba de suma
   */
   public void testSuma()
   {
      Entero e1 = new Entero();
      e1.setValor(4);
      m_entero.suma(e1);
      assertEquals(m_entero.getValor(),9);
   }

   public static Test suite()
   {
      TestSuite suite = new  TestSuite(EnteroTest.class);
    return suite;
   }
}

Hay que subrayar que la preparación de caso de prueba (o fixture) se realiza en el metodo llamado setUp(). Este metodo siempre es invocado (de forma automática) antes de que se invoque uno de los metodos de la clase de prueba.

Por otro lado, dentro de las pruebas, se usa el metodo assertEquals para verificar que dos valores sean iguales. La clase TestCase provee distintos metodos para comprobar que dos valores sean iguales, distintos o bien que un objeto es nulo o no.

Normalmente, cada test se realiza creando una instancia de la clase de prueba y pasandole en una cadena el nombre del metodo correspondiente a la prueba que se quiere realizar, por ejemplo:

TestCase test = new EnteroTest("testSuma");
test.run();

Sin embargo esto es complicado cuando se tiene un numero elevado de pruebas a realizar. Para ello se utiliza el concepto de suite. Una suite corresponde a un conjunto de tests que se realizan de manera secuencial. La creación de una suite es simplificada con la clase TestSuite. En el ejemplo anterior, el metodo suite (notese que es estático) recibe cómo parametro el nombre de la clase de prueba. Cuando esto ocurre la suite de pruebas va a incluir todos los metodos de prueba que empiezen por test, de ahi la importancia de seguir la convención de nombrado.

NOTA: Al compilar y ejecutar es necesario hacerlo desde la línea de comando.

Una vez que hemos hecho la prueba, es posible complilarla y ejecutarla de la manera siguiente desde la línea de comando:

$javac  -classpath junit.jar -d build/ src/ejemplo/*.java src/test/ejemplo/*.java

$java -cp build/:junit.jar junit.textui.TestRunner test.ejemplo.EnteroTest

...
Time: 0.019
 
OK (3 tests)


Ejercicio 1: Prueba simple

Codificar la clase Entero y su clase de prueba. Efectuar las pruebas y verificar que el resultado sea correcto.

  • Qué pasa si remplazas junit.textui.TestRunner por junit.swingui.TestRunner ?
  • Qué pasa si modificas la clase Entero en el metodo suma y cambias la suma por una resta y luego re-ejecutas las pruebas?
En este primer ejercicio, te puede parecer exagerado que la clase de prueba sea más grande que la clase probada, sin embargo eso no es siempre el caso, como veremos en el ejemplo siguiente.

Ejercicio 2: Integración de Ant y Junit

Introduce la información siguiente en tu script ant.

Dentro de target init:

<property name="junitreports.dir" value="${doc.dir}/junitreports"/>
Dentro de target prepare:
<mkdir dir="${junitreports.dir}"/>
Dentro de target clean:
<delete dir="${junitreports.dir}"/>
<target name="test" depends="compile">
    <junit printsummary="true" >
        <formatter type="xml"/>
        <test name="${maintestclass}"/>
        <classpath>
            <pathelement location="${build.dir}" />
        </classpath>
    </junit>
    <junitreport todir="${junitreports.dir}">
        <fileset dir=".">
                <include name="TEST-*.xml"/>
        </fileset>
        <report format="frames" todir="${junitreports.dir}/html"/>
    </junitreport>
</target>

Ejecuta el target test y ahora apunta tu navegador al directorio doc/junitreports/html


Ultima actualización: 16 Febrero 2005
contacto: hcm@xanum.uam.mx
Homepage