Last Updated: 2019-04-30

¿Por qué poblar un esquema de entidades?

Al hablar de programación orientada a objetos, muchas veces se presentan escenarios donde las relaciones entre clases son complejas, lo cual genera la necesidad de tener un manejo especial y cuidadoso al momento de relacionar las entidades entre sí. Para comprobar el comportamiento de una aplicación de este estilo, es una buena idea generar datos de prueba que simulen el entorno al que estará expuesta la aplicación en producción.

Además, poblar estos esquemas de entidades permite comprobar que las relaciones y el modelado planteados sobre el problema son adecuados y satisfacen los requerimientos indicados sin generar problemas.

¿Qué es Podam?

Podam es una herramienta que permite generar de forma automática objetos de Java, también conocidos como POJOs (Plain Old Java Objects), teniendo en cuenta todas las particularidades de los datos que puedan existir. La herramienta se adapta para generar datos de cualquier clase de Java que se haya definido en un proyecto.
Podam se distribuye como una dependencia para proyectos de Java y se aloja en el repositorio de Maven Central (puede conocer el repositorio desde el siguiente enlace: https://search.maven.org/search?q=a:podam). Esto permite la integración de Podam con proyectos de Spring o Maven.

Para ver la documentación oficial del proyecto de Podam puede dirigirse a su sitio web oficial en el siguiente enlace: https://mtedone.github.io/podam/index.html.

¿Qué construirá?

Al final de este tutorial usted tendrá:

¿Qué aprenderá?

Al realizar este tutorial usted aprenderá:

¿Qué necesita?

En este tutorial tomará como guía una aplicación sencilla, que funciona por consola, y que representa un pequeño sistema de compra de artículos por unidad. El proceso para adquirir dicha aplicación es parte de un paso posterior, y requiere que usted cuente con un proyecto de Maven vacío como se explica en el anexo del siguiente enlace: https://misovirtual.virtual.uniandes.edu.co/codelabs/annex-maven-projects/index.html#0

Ver las clases del modelo UML

Para modelar las entidades presentes en el problema, se diseñó el siguiente diagrama UML que explica las clases, con sus atributos y relaciones, que permiten modelar el contexto de la aplicación:

Imagen 3. Diagrama de clases del problema en cuestión

Como lo muestra el diagrama, se tendrán en cuenta 4 clases diferentes que representan, respectivamente, a un vendedor con sus artículos disponibles y vendidos, y a un cliente con las compras que ha realizado sobre diferentes artículos. Los atributos de cada entidad corresponden a información básica: el nombre, el correo y un número de teléfono en el caso del cliente y del vendedor; la fecha, el monto total y el estado de la compra; y el nombre, la descripción, la categoría y el precio de un artículo. La principal funcionalidad que tendrá disponible el programa de consola será la de realizar una compra como cliente.

En este caso, hacer uso de Java como lenguaje de programación es adecuado dado su manejo de clases y la facilidad de diseñar un programa de consola.

Obtener el código fuente de la aplicación

En este tutorial, usted utilizará una sencilla aplicación desarrollada en Java como base. Esta está alojada en un repositorio de GitHub, pero usted seguirá el proceso de creación de su proyecto de forma guiada en este tutorial en lugar de trabajar sobre el código del repositorio.

En pasos anteriores usted creó un proyecto base con la estructura de Maven. Podrá ver un directorio con el nombre src, que contendrá los archivos .java que serán compilados para crear la aplicación. Dentro de este, podrá ver un esquema de subdirectorios definido por el identificador que le asignó a su aplicación al momento de crearla. En este caso, esta ruta es src/main/java/com/example/podam, pero puede cambiar según el identificador que usted haya utilizado. Allí ubicará los archivos del código fuente original.

Descargue, en otro directorio, el código de la aplicación base desde el siguiente enlace: https://github.com/jespitiaa/PodamTutorial/archive/versionInicial.zip. Esto descargará un archivo comprimido en formato zip a su computadora. Descomprímalo, con las herramientas correspondientes, en su sistema operativo y podrá ver que existen los mismos directorios que en su proyecto.

Usted operará sobre el contenido de dos directorios a la par. El directorio del código fuente del proyecto que acaba de descomprimir (referencia) y el directorio del código fuente del proyecto que usted creó en el paso anterior (propio). Abra el primero de estos y podrá ver un archivo .java para cada una de las clases del problema y un archivo llamado App.java, como se muestra a continuación:

Archivos para las clases y uno para la integración: ArticuloUnitario.java, Cliente.java, Compra.java, Vendedor.java y App.java\n

Imagen 4. Archivos de código fuente para la aplicación de ejemplo

Copie únicamente los archivos ArticuloUnitario.java, Compra.java, Cliente.java y Vendedor.java desde el directorio del código fuente del proyecto original hacia el directorio del código fuente del proyecto que usted creó. Aún no modifique el archivo App.java que se creó en su proyecto. Una vez haya copiado los demás archivos, ábralos en un editor de texto o un ambiente de desarrollo.

Podrá ver que, en todos estos archivos, la primera línea de código corresponde a la definición del paquete del proyecto (referencia) al que pertenece el archivo originalmente. Esta línea es de cuidado y debe ser revisada antes de proceder con la ejecución del proyecto. Para poder ejecutar la aplicación, debe asegurarse que los archivos estén empaquetados de forma adecuada con respecto a su proyecto local. Agregue al final de la clase Compra el siguiente método:

public ArrayList<ArticuloUnitario> getArticulos() {

return articulos;

}

Para esto, abra el archivo App.java que se ha creado en su proyecto de Maven y preste especial atención a la primera línea que se encuentra en él. Esta contendrá el nombre del paquete creado para su proyecto, el cual debe utilizar para todas las demás clases. En caso de que sea distinto a com.example.podam, copie esta línea y reemplácela en la primera línea de cada uno de los archivos.

Copie ahora el archivo App.java desde el proyecto original hacia su proyecto. Si el identificador del paquete era diferente, debe volver a reemplazar la primera línea de este archivo. Una vez haya transferido estos archivos, puede borrar libremente el proyecto original y mantener el que usted ha venido creando.

Ahora que se aseguró de prevenir errores en la estructura del proyecto, explore el código fuente de cada archivo.

Comprender el código fuente de la aplicación

El archivo App.java contiene el método main que permitirá la ejecución de la aplicación. En este se definen métodos estáticos auxiliares para la interacción por consola y se define un escenario de ejemplo para el sistema de venta de artículos para confeccionistas independientes.

Podrá ver que esta aplicación tiene muchas oportunidades de mejora, pero una de las más relevantes es la instanciación de entidades como parte del código. Esto puede causar un sesgo para determinar si la aplicación funciona correctamente o no y, por ende, es un buen escenario para hacer uso de Podam y probar múltiples escenarios.

Los otros cuatro archivos contienen las clases que se utilizarán para crear los POJOs de la aplicación y el código que hay dentro de ellas corresponde a lo que se mostró en el diagrama de clases de la imagen 3.

Otra observación que es importante que haga, es que aún no se ha hecho uso de Podam en el proyecto en lo absoluto, ni se han definido pruebas unitarias.

Ejecutar la aplicación

Ahora que tiene su proyecto de maven con el código fuente respectivo, puede ejecutar la aplicación para comprender el comportamiento real de la misma. Se sugiere que utilice un IDE adecuado para Java, ya que le permite ejecutar la aplicación fácilmente por medio de un botón típicamente llamado Run, con un ícono de reproducción. Sin embargo, no es necesario que cuente con un IDE, pues también puede manejar y ejecutar su proyecto desde una terminal.

Para ejecutar la aplicación desde su terminal, ubíquese en el directorio raíz del proyecto que usted creó. Debe compilar los archivos de código fuente y luego ejecutarlos. (Puede aprender más sobre este proceso en el tutorial del siguiente enlace: http://tutorials.jenkov.com/java/java-project-overview-compilation-and-execution.html)

Ejecute el siguiente comando para compilar todos los archivos de código fuente en un directorio llamado classes:

javac src\main\java\com\example\podam\*.java -d classes

Desde un explorador de archivos podrá ver que se creó dicho directorio y que este contiene un archivo en formato .class para cada archivo .java que tenía inicialmente. Si le sale un error referente a que no existe la carpeta classes, creela manualmente y ejecute de nuevo el comando. Ahora, ejecute el siguiente comando para correr la aplicación definida en el método main del archivo App:

java -cp classes com.example.podam.App

Podrá ver que la aplicación de consola muestra un menú para interactuar desde el terminal que abrió. Ingrese un nombre, un correo cualquiera y un número de teléfono cualquiera para crear un usuario; luego de esto podrá interactuar con el menú de la tienda, que le muestra el listado de vendedores y productos, y le ofrece la opción de comprar. Recuerde que la aplicación es un proyecto de prueba para simular una aplicación, por ende no es persistente y su información está declarada como parte del código fuente.

Incluir Podam en su proyecto

Ahora que conoce la aplicación, comprenderá la necesidad de probar que los esquemas y las relaciones sean correctas más allá del caso instanciado. Con Podam podrá generar los datos de prueba y validar la estructura propuesta para modelar el problema.

Para incluir Podam en su proyecto de Maven, debe modificar el archivo pom.xml, el cual permite realizar configuraciones a nivel de proyecto. Abra el archivo en un editor e incluya las siguientes líneas en la sección "dependencies" del mismo:

(...)
<dependency>
  <groupId>uk.co.jemos.podam</groupId>
  <artifactId>podam</artifactId>
  <version>7.2.3.RELEASE</version>
</dependency>
(...)

Ahora debe actualizar el proyecto para que efectivamente descargue e incluya las dependencias que acaba de declarar. Si está trabajando con un ambiente de desarrollo, podrá actualizar el proyecto por medio de la interfaz gráfica (como se indica en el siguiente enlace, para Eclipse: https://stackoverflow.com/questions/2555845/how-to-update-maven-repository-in-eclipse), o en algunos casos, de forma automática. Sin embargo, para actualizarlas manualmente con las herramientas de CLI, ejecute el siguiente comando en el directorio raíz del proyecto:

mvn clean install -U

Definir las estrategias de generación con Podam

Ahora que cuenta con las librerías de Podam, puede hacer uso de sus clases y anotaciones para definir la forma en que se va a generar cada uno de los datos. Ingrese al siguiente enlace para consultar las diferentes anotaciones soportadas por Podam: https://mtedone.github.io/podam/annotations.html.

Como puede ver, Podam cuenta con anotaciones para indicar la estrategia de generación de los atributos de sus clases. Esto permite personalizar la generación de algunos valores como, por ejemplo, la cantidad de caracteres en el caso de las cadenas de texto. Sin embargo, estas anotaciones no son necesarias en este tutorial, ya que las Factories de Podam que generan los datos al momento de la prueba saben generar datos genéricamente válidos según el tipo con el cual cada atributo fue declarado.

No obstante, la anotación @PodamExclude es necesaria en este y muchos otros escenarios para evitar que ciertos atributos de un objeto se generen por defecto. En particular, en este proyecto, los clientes cuentan con un listado de compras y los vendedores cuentan con un listado de artículos vendidos, los cuales deben empezar vacíos al ejecutar el programa. Ubique en el archivo Cliente.java la línea que declara el atributo private ArrayList<Compra> compras, y en el archivo Vendedor.java la línea que declara el atributo private ArrayList<ArticuloUnitario> artVendidos. Escriba esta anotación en la línea inmediatamente anterior a las líneas de declaración de los atributos. Adicionalmente, agregue la importación del paquete que contiene la anotación en ambas clases. Esta importación se debe hacer al inicio del archivo en la línea 5 aproximadamente.

5 import uk.co.jemos.podam.common.PodamExclude;

...<Vendedor>

16 @PodamExclude

17 private ArrayList<ArticuloUnitario> artVendidos;

...<Cliente>

14 @PodamExclude

15 private ArrayList<Compra> compras;

Definir la prueba unitaria

Ahora que ha indicado las estrategias de generación que Podam debería utilizar para cada una de sus clases, usted probará los esquemas de generación y también realizará una prueba funcional con un comportamiento similar al de la aplicación base definida en App.java.

Las pruebas unitarias las creará con ayuda de la librería JUnit de Java. Es posible que al momento de crear su proyecto de Maven se haya incluido automáticamente una versión diferente a la 4. Sin embargo, en este tutorial hará uso de la versión 4.12 de JUnit, puesto que es la más popular y soportada, además de contar con múltiples ventajas ante las versiones anteriores.

Revise la versión de JUnit incluida en su archivo pom.xml. En caso de que no exista la dependencia o la versión sea diferente a la 4.12, cambie el código XML donde se declara la dependencia a JUnit por el siguiente:

(...)
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
(...)

Su archivo pom.xml luego de esto debería verse de forma similar a lo que se muestra en la siguiente imagen:

Imagen 5. Contenido de ejemplo del archivo pom.xml

Recuerde que, como se le indicó anteriormente, es necesario que actualice sus dependencias en el proyecto para descargar efectivamente las librerías desde el repositorio de Maven Central.

Ahora que cuenta con la versión adecuada, podrá crear la prueba de este tutorial. Revise el contenido del directorio src/test/java/<App/Artifact/Id> (en este caso, src/test/java/com/example/podam). Si encuentra algún archivo .java adicional a los que copió del repositorio, quiere decir que se generó un archivo de forma automática para el código fuente de la prueba. Elimine cualquier archivo de este tipo.

Una vez el directorio de las pruebas se encuentre limpio, cree un nuevo archivo que contendrá la prueba de integración. Esto lo puede hacer con ayuda de su IDE, o simplemente creando un archivo IntegrationTest1.java y agregando el siguiente código fuente:

package com.example.podam;

import static org.junit.Assert.*;
import org.junit.Test;
import uk.co.jemos.podam.api.PodamFactory;
import uk.co.jemos.podam.api.PodamFactoryImpl;

public class IntegrationTest1 {

    @Test
    public void test() {
            // Simplest scenario. Will delegate to Podam all decisions
            PodamFactory factory = new PodamFactoryImpl();

            // This will use constructor with minimum arguments and
            // then setters to populate POJO
            Cliente myPojo = factory.manufacturePojo(Cliente.class);
            Vendedor v = factory.manufacturePojo(Vendedor.class);
            ArticuloUnitario art = factory.manufacturePojo(ArticuloUnitario.class);

            System.out.println("-----------Entidades iniciales---------------");
            System.out.println(myPojo.toString());
            System.out.println(v.toString());
            System.out.println(art.toString());

            System.out.println("-----------Menu hipotético de la app---------------");
            System.out.println("ESTADO INICIAL:-----------------------------------");
            v.imprimirDisponibles();
            int longInicial = v.getDisponibles().size();
            v.ofrecer(art);

            myPojo.comprar(v.getDisponibles().get(0));
            v.vender(0);

            int longFinal = v.getDisponibles().size();

            System.out.println("ESTADO TRAS COMPRA/VENTA DE PRODUCTO:---------------------------");
            assertEquals(longInicial, longFinal);
            v.imprimirDisponibles();
            System.out.println("----------------------------------------------------------------");
            System.out.println("Artículo en lista de vendidos del vendedor:");
            System.out.println(v.getVendidos());
            System.out.println("Artículo comprado por el cliente");
            System.out.println(myPojo.getCompras());

            assertEquals(v.getVendidos().get(0).toString(), myPojo.getCompras().get(0).getArticulos().get(0).toString());
    }
}

Recuerde asegurarse de que la primera línea, donde se declara el paquete, debe corresponder con el identificador que usted ha estado utilizando para su aplicación en otros archivos de código fuente.

Revise ahora el código que acaba de agregar. Notará que se declararon atributos que contienen un vendedor y un cliente, como se hizo en la aplicación base, pero en este caso son creados con la ayuda de la clase PodamFactoryImpl. Además, en la prueba se realiza una compra del primer artículo del vendedor por parte del cliente. Podrá notar que en este caso se incluyeron dos aserciones que comprueban que la compra fuera efectiva en el sentido que: el artículo fue eliminado de los artículos disponibles, pasó a ser parte de los artículos vendidos y corresponde idénticamente al artículo que es parte del objeto Compra del cliente.

Ejecutar la prueba unitaria

Ahora que comprende el sentido de la prueba que acaba de crear, ejecute el archivo que contiene la prueba para que se cree un escenario similar al esperado de la aplicación, pero con datos aleatorios generados gracias a Podam.

Como podrá suponer, ejecutar la prueba una vez no bastará para validar por completo la aplicación. Con una prueba de este tipo puede encontrar casos límite si la ejecuta múltiples veces y estudia el comportamiento de cada caso. Así mismo, diseñar estas pruebas para su software le permite identificar oportunidades de mejora para la implementación que ha realizado de su código.

Para ejecutar la prueba, puede hacer uso de las herramientas provistas por la interfaz de usuario de su ambiente de desarrollo, pero en cualquier caso, podrá ejecutar sus pruebas por medio de las herramientas de CLI de Java/Maven también. Para esto, en una terminal, ubíquese en el directorio donde creó sus archivos de prueba y ejecute el siguiente comando:

mvn -Dtest=IntegrationTest1 test

Este comando le indicará por medio de la consola el resultado de cada una de las pruebas que usted definió previamente.

Podrá ver en la consola una serie de registros creados en la prueba con la instrucción System.out.println() para visualizar el estado de los datos creados y, finalmente, un resultado como el de la siguiente imagen:

Registros de consola Results:\nTests run: 1, Failures: 0, errors:0, skipped:0\nBUILD SUCCESS\nTotal time\nFinished at

Imagen 6. Resultado en consola indicando que la prueba ejecutada fue exitosa

¡Felicidades!

Al completar este tutorial usted se ha familiarizado con el uso de Podam para generar datos de prueba sobre los esquemas de clases en un proyecto de Java con Maven.

Ahora usted podrá diseñar pruebas unitarias sobre un proyecto de Java orientado a objetos en cualquier otro escenario y así validar que las clases y relaciones son adecuadas para modelar el contexto que define la aplicación y manejar la información que hará parte de ella.

Créditos

Versión 1.0 - Mayo 30, 2020

Juan Sebastián Espitia Acero

Autor

Norma Rocio Héndez Puerto

Revisora

Mario Linares Vásquez

Revisor