Eclipse -- II -- Integración con JUnit

Puede encontrar la versión original de este artículo en Inglés en:

http://www.onjava.com/

Introducción

Ya se han escrito muchos libros sobre los tests automatizados, pero muy pocos prestan atención a la cuestión de cómo organizar dichos tests. Cuanto más tests se escriban más difícil es saber donde ponerlos o incluso llamarlos. Esto se convierte en un problema importante con el auge del Desarrollo Dirigido al Test (TDD), que ha popularizado la Extreme Programming (XP). Puedes pensar en TDD como "Desarrollo a Través de Tests".

Los mayores beneficios de TDD son:

  • Antes de escribir cualquier fragmento de código, se debe escribir un test automátizado para chequear la funcionalidad de ese futuro código. Como el código no existe todavía, inicialmente no pasará el test.
  • Despues de que empiecen a pasarse los tests, se debe eliminar el código duplicado.

Organización de Tests

Antes de empezar a escribir tests, primero sería deseable ver cómo organizar los tests automatizados.

Se debería considerar que hay diferentes tipos de tests:

  • Tests de Unidades: sirven para chequear la corrección de varios módulos (es decir, clases). Si el objeto necesita acceder a alguna fuente de datos externa, como una base de datos, se simulan con objetos mock, pero sólo en el caso de que recrear la fuente de datos real fuera díficil en un entorno de prueba.
  • Tests de Cliente: Tests funcionales de sistema y aceptación. Todos estos tests chequean el comportamiento de un sistema completo. En la metodología XP, estos tests los escriben los clientes, dando el esqueleto del programa.
  • Tests de Integración: son un cruce entre los tests de cliente y los tests de unidad. Los tests de integración ayudan a probar la interacción de varios niveles de la aplicación. Los objetos mock no se utilizan normalmente en este tipo de test, porque podrían incrementar la duración del test. Algunas veces los tests de integración también demandan la presencia de un entorno de prueba especial, como una base de datos rellena con datos de prueba, e incluso liberías externas especiales.
  • Tests de Desarrollador: son los tests que los desarrolladores utilizan para verificar todo el código, nuevas partes de él, y/o nuevas funciones. Para cualquier desarrollador es importante generar nuevos tests para probar el código siempre que sea posible.

Para el resto de este artículo, cuando digamos "test", nos referiremos a los tests de desarrollador.

Durante el desarrollo, un programador algunas veces se pregunta: ¿habrá en el sistema algún tests para este comportamiento, y donde podré encontrarlo? Un ejemplo clásico es una corrección de bugs básica, en la que se encuentra un error, pero no mediante tests automatizados. La secuencia de eventos que resulta de esta situación podría ser:

  1. Se busca el tests para la funcionalidad específica (es probable que el test exista, pero que contenga un error).
  2. Si el tests no existe, o no cubre una situación en la que haya un error, se escribe un test que lo revele.
  3. Ahora se necesita estar convencido de que el código no pasará el nuevo test.
  4. Se corrige el bug.
  5. Se ejecuta el test.
  6. Se confirma que lo pasa.

Desde luego que hay distintas variaciones de este proceso, pero la idea debería quedar clara: sólo se corrige un error cuando haya un test lo revele.

Ahora consideremos como debería resolver está situación un desarrollador. Para buscar si existe un test para esa funcionalidad:

  • Se puede utilizar ciertos entornos de desarrollo integrados (IDEs) que permiten buscar los lugares en que se utilicen las clases y los métodos correctos.
  • Se puede crear un situación de error conocida e inspeccionar en qué fragmento de código está el error.
  • Por último y no menos importante, se puede escribir un test y situarlo en una de las clases de tests existentes. Si se comete un error escribiendo el test y se duplica código, quizás algún colega lo note y pueda corregirlo.

Nombrar los Tests

Estamos casi listos para crear un test, por eso ahora debe elegir un nombre para el test. Se podría decir, "Eso no es un problema: se pone la palabra 'Test' delante del nombre de la clase, y ya está!". No tan rápido! Veamos los problemas que como esto puede traer:

  • Cuando se utiliza TDD, la clase o método que se va a probar podría no existir aún.
  • También es posible que un test cubra varios métodos, o incluso varias clases.

Estos son sólo los problemas más importantes, hay muchos más.

Permítame ofrecerle una recomendación sobre los nombres de tests: el nombre de una clase de test debería indicar que es una clase de test, y lo que chequea exactamente, tanto si repite o no el nombre de la clase a probar. Esto es fácil. No se preocupe de si el nombre es demasiado largo o embarullado. Se describe a sí mismo, y esta es la idea!

Crear un Test

Crearemos el primer test con la ayuda de la herramienta JUnit en el IDE Eclipse. Se asume que ya tiene instalada una versión reciente de este producto, pero si no es así, siempre puede descargarla desde su site oficial. Las últimas versiones de Eclipse ya traen incorporado el Plug-in de JUnit, pero si su versión es anterior, tendrá que descargar e instalar JUnit desde su site oficial.

Para crear un proyecto Java:

  • Arranque Eclipse.
  • Pulse File -> New -> Project, luego elija Java y pulse Next.
  • En el wizard que aparece escriba ProjectWithJUnit como nombre del proyecto:

  • Pulse sobre Finish. Y se generará el nuevo proyecto en el IDE:

Ya está listo para empezar a desarrollar el ejemplo "Hello World". Siga las reglas de TDD y cree el test incluso antes de tener ningún código. Con el objetivo de tener algo por donde empezar, asumiremos que la futura clase se llamará HelloWorld y que tendrá un método say(), que devolverá algún valor String ("Hello World," por ejemplo).

  • Para crear dicho test, pulse con el botón derecho sobre el proyecto ProjectWithJUnit en la ventana del Package Explorer y seleccione New -> JUnit Test Case; Eclipse detectará que no hemos incluido en el classpath del proyecto la librería de JUnit y pedirá confirmación para hacerlo:

  • Dígale que si y aparecerá el wizard para crear la nueva clase.
  • Escriba com.tests como el nombre del paquete donde va a residir la clase y como nombre de la clase de test (Test case) puede utilizar TestThatWeGetHelloWorldPrompt (si, ya lo se, es demasiado largo, pero indica claramente lo que hacer, ¿no?):

  • Pulse Finish y Eclipse se encargará de crear la nueva clase:

  • Ahora le toca añadir código a la clase para que se parezca a esto:
    import junit.framework.TestCase;
    
    public class TestThatWeGetHelloWorldPrompt
        extends TestCase {
        public TestThatWeGetHelloWorldPrompt(
            String name) {
            super(name);
        }
        public void testSay() {
            HelloWorld hi = new HelloWorld();
            assertEquals("Hello World!", hi.say());
        }
        public static void main(String[] args) {
            junit.textui.TestRunner.run(
                TestThatWeGetHelloWorldPrompt.class);
        }
    }
    

El código de la clase no es muy complejo; sólo es un poco inusual. Sin embargo, vamos a examinarlo en detalle. Extiende la clase TestCase de JUnit, que se define en el Javadoc de JUnit como "una instalación para ejecutar múltiples tests". JUnit también tiene TestSuite, que es un conjunto de clases de tests relacionadas, pero no lo cubriremos en este artículo.

Para crear el sencillo test, necesita seguir estos pasos:

  1. Cree un ejemplar de junit.framework.TestCase.
  2. Defina tests que no devuelvan nada (void) cuyos nombres empiecen con el string "test" (como testWasTransactionSuccessful(), testShow(), etc.).

TestThatWeGetHelloWorldPrompt.java cumple estos dos criterios: es una subclase de TestCase y tiene un método llamado testSay(). Este método utiliza una llamada a assertEquals(), que compara el valor que esperamos recibir con el valor devuelto por el método say().

El método main() se utiliza para ejecutar el test y presentar su salida. El método TestRunner proporciona salidas tanto gráficas como de texto. Utilizamos la salida de texto porque es la que soporta Eclipse y es la adecuada para nosotros. Una vez ejecutados, la versión de texto de los tests mostrarán sus resultados y Eclipse utilizará esa salida de texto para crear su propia representación gráfica.

Bueno, según la metodología de TDD, tiene que ejecutar el test para ver que es lo que falla.

  • Seleccion la clase TestThatWeGetHelloWorldPrompt.java y en el menú elija Run -> Run as -> JUnit Test
  • Una vez ejecutada cambiará el aspecto de la vista de la pantalla y en la parte izquierda de la pantalla verá la ventana de JUnit en lugar del Package Explorer. La venta de JUnit mostrará una barra roja indicando que el test no se ha pasado con éxito, y abajo podrá ver los detalles de esos fallos:

Perfecto! Realmente ha fallado. Ahora podemos crear el código que funcione en nuestro proyecto:

  • Puls con el botón derecho en el título ProjectWithJUnit en la ventana del Package Explorer, luego elija, New -> Class.
  • En el wizard que aparece escriba com.tests como el nombre del paquete para esta clase y HelloWorld como nombre de la clase. No marque ninguno de los checkboxes que hay en el wizard.

  • Pulse Finish y teclee el siguiente código dentro de la clase HelloWorld:
        public String say() {
            return("Hello World!");
        }
    

Es muy simple y no hace falta ningún comentario. Ejecutemos el test de nuevo para ver los resultados.

Ejecute el test de la forma que se vió arriba (recuerde seleccionar primero la clase TestThatWeGetHelloWorldPrompt.java en el Package Explorer.

Funciona! Hemos pasado el test y Eclipse nos lo indica mostrando una barra verde en la ventana de JUnit:

Ahora vamos a hacer que falle de nuevo, pero por una razón diferente. Esto nos ayudará a descubrir cómo JUnit cubre e informa de los diferentes tipos de errores. Edite la sentencia assertEquals("Hello World!", hi.say()); y escriba assertEquals("Hello Me!", hi.say());. Con esto se cambia el valor de retorno esperado. Si se ejecuta este test de nuevo, la barra de la ventana de JUnit será otra vez roja, y en la parte inferior de la ventana de JUnit mostrará una explicación de lo que está fallando:

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP