¿Cómo hacer pruebas de componentes para el Dataflow?
Introducción
Para aumentar las capacidades del Dataflow es posible desarrollar etapas personalizadas que se pueden utilizar en los pipelines que se creen con el propio Dataflow del mismo modo que cualquiera de los componentes propios del Dataflow.
Este artículo describe cómo se pueden hacer test automáticos con JUnit para probar las esatapas personalizadas que se desarrollen.
Para mostrar ejemplos, usaremos un proyecto cuyo código completo puede conseguirse en github. Dicho proyecto incluye ejemplos de pruebas para los componentes JDBC del propio Dataflow. De esta forma muestra ejemplos tanto para etapas de tipo origen, de tipo destino y de tipo procesadores.
Configuración del proyecto
El proyecto de ejemplo (github) usa Maven para la gestión de las dependencias. A continuación se describen las depedencias que se han utilizado.
Versiones utilizadas.
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<sdc.version>3.23.0</sdc.version>
<junit.version>5.9.3</junit.version>
<h2.version>2.2.220</h2.version>
</properties>
Librería JUnit, en este caso estamos utilizando JUnit 5.
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
En este caso, dado que estamos probando la librería JDBC del dataflow, necesitamos declarar la libería que tiene los componentes que vamos a probar. En un proyecto de desarrollo de componentes esto no sería necesario ya que los test estarían en el propio proyecto.
<dependency>
<groupId>com.streamsets</groupId>
<artifactId>streamsets-datacollector-stagesupport</artifactId>
<version>${sdc.version}</version>
<scope>test</scope>
</dependency>
En muchos casos necesitaremos librerías adicionales si queremos probar las conexiones externas. Esto dependerá del tipo de test que se quiera realizar, unitarios con mocks, de integración con los sistemas externos. En este caso lo vamos a hacer utilizando una base de datos para probar las conexiones directamente. Para ello utilizamos la base de datos en memoria H2.
Finalmente, es necesario declarar las dependencias propias del dataflow que se utilizarán para ejecutar las estapas a probar y poder comprobar los resultados.
Prueba de Orígen
En este ejemplo para probar el origen JDBC arrancamos una base de datos H2 y la poblamos con unas tablas para probar.
Del mismo modo, al finalizar el test limpiamos la base de datos.
Para realizar la prueba lo primero que hacemos es crear un componente de tipo origen JDBC
Los valores de inicialización dependen del tipo de componente, por lo que los utilizados en este ejemplo son los específicos del origen de JDBC.
Lo siguiente es crear un objeto SourceRunner que nos va a permitir ejecutar las “lecturas” del origen.
Una vez hecho esto simulamos una secuencia de lecturas, y si queremos escrituras, de la base de datos con el origen. Además nos aseguramos de liberar los recursos del runner cuanto terminamos de ejecutar el test.
No merece la pena detallar el test porque es específico del componente que estamos probando en el ejemplo. Lo importante es fijarse en cómo se usa el objeto de la clase SourceRunner (runner en el ejemplo) para ir produciendo registros. También es útil fijarse en cómo se pueden comprobar los valores de los datos obtenidos para poder comprobar que los valores obtenidos son los esperados.
El ejemplo completo se puede ver en github.
Prueba de Destino
Para probar la escritura en el destino se ha usado una estrategia similar a la empleada para probar la lectura. Por lo que no vamos a repetir la parte de código similar de configurar la base de datos. Para ver el ejemplo completo se puede ver en github.
Las mayores diferencias es que se creará un objeto de tipo destino, JdbcTarget, en nuesto ejemplo.
Se crea un TargetRunner para ejecutar la escritura. Además, para para escribir hay que crear los registros que formarían el batch de escritura. Finalmente, se usa el TargetRunner para escribir en el destino.
Finalmente hay comprobar que se ha escrito en el destino. En este ejemplo comprobando si se ha escrito en la base de datos.
Prueba de un Processor
Este caso es muy similar al de los Orígenes y los Destinos. La mayor diferencia radica en que se utiliza un componente de tipo processor y un runner de tipo ProcessorRunner.
El resto de comprobaciones son similares a las de destino y origen. Se puede ver el ejemplo completo en github.