java - run - Integración continua: mantener el esquema DB de prueba actualizado
test de jenkins español (6)
Actualmente uso un enfoque similar. He estado investigando las herramientas de migración de db y no he encontrado ninguna que resuelva el problema que describes.
El problema es que, a veces, un cambio de esquema requiere que se modifiquen los datos para permitir la creación de nuevas restricciones, etc. En este caso, si se ignoraron las sentencias de actualización de datos, la migración fallaría.
¿Agregaría una secuencia de comandos sql a su suite de pruebas que borra todos los datos en la base de datos que le corresponden?
Entonces el proceso sería:
- ejecutar db migration.
- ejecutar script para eliminar todos los datos en db.
- cargar datos de prueba
- ejecutar pruebas
Estoy configurando un servidor de integración continua (Hudson) para construir un proyecto de Java y ejecutar las pruebas de unidad / integración pertinentes. La mayoría de estas pruebas accede a una base de datos y los datos de prueba se guardan en un archivo DbUnit XML.
Estoy buscando una manera de mantener automáticamente el esquema de la base de datos de prueba actualizado. Actualmente, el script SQL para una versión en particular se almacena en un directorio que lleva el nombre de la versión de lanzamiento:
└───scripts
├───0.1.0
├───0.1.1
├───0.1.2
├───0.1.4
Por ejemplo, el script SQL para la versión 0.1.4 es
scripts/0.1.4/script-0.1.4.sql
El problema es que estos scripts contienen una mezcla de cambios de esquema (por ejemplo, ALTER TABLE ...) y cambios en las tablas estáticas (por ejemplo, agregar un nuevo rol a la tabla USER_TYPE).
En el caso de las pruebas unitarias, solo quiero aplicar los cambios de esquema, porque como se mencionó anteriormente, todos los datos para las pruebas unitarias se guardan en un archivo DbUnit XML. Aunque podría separar estos dos tipos de cambios en la base de datos en diferentes archivos, a menudo existirá una dependencia entre los cambios del esquema y los cambios en los datos que deberán aplicarse de alguna manera cuando la versión se aplique a QA, producción, etc.
De todos modos, esta es solo una forma muy larga de preguntar si alguien ha ideado una forma robusta de mantener automáticamente actualizado su esquema de prueba. Sé que Unitils tiene algo de apoyo para mantener un esquema de prueba actualizado, pero no estoy seguro si puede ''ignorar'' las declaraciones de actualización de datos en los scripts SQL delta.
Lo que hago en mis pruebas:
- Guardo una versión de DB en alguna parte
- En la primera prueba, destruyo toda la base de datos y la construyo desde cero
- Ejecuto cada actualización de esquema en una prueba individual
- Ejecuto el módulo "actualizar DB" como una prueba individual (no debe hacer nada porque ya se han aplicado todos los cambios). Opcionalmente, derribo el DB nuevamente y lo ejecuto una vez.
- Cargué los datos de prueba en el DB (algunas de las pruebas anteriores lo harán si corrigen errores de datos).
Ahora, el DB de prueba está listo para las pruebas "reales" (aplicación). Después de cada una de las pruebas de aplicación, retrotrajo la transacción actual para que la base de datos de prueba nunca cambie después de la instalación.
Para hacer que las pruebas sean más rápidas, generalmente tengo tres suites de prueba: una que contiene la configuración de base de datos, una que contiene solo las pruebas de aplicación y otra que contiene las otras dos suites. Esto me permite restablecer rápidamente el DB de prueba y ejecutar una única prueba desde el conjunto de aplicaciones.
Lo que hemos encontrado como la forma más manejable de gestionar la evolución gradual de Live / Test DB Schemas es usar una herramienta de gestión de la migración de esquemas como Liquibase
Esto nos permite aplicar los últimos cambios de esquema al entorno que elijamos, probemos o no, de forma consistente, lo que nos permite ejecutar cualquier tipo de automatización que deseemos con el esquema actualizado.
Yo uso migrateDB para gestionar este problema.
Esta herramienta se basa en la noción de que hay "pruebas" que puede realizar (a través de SQL) en su base de datos para ver si se ha aplicado un cambio de base de datos dado, y un conjunto de acciones correlativas para realizar si una prueba "falla". Por ejemplo, puede que necesite consultar el esquema de la metatabla para ver si existe una tabla o columna, y si no lo hace, créelo. O bien, es posible que desee ver si existe una determinada fila en una tabla, y si no, insértelo. Viene con algunas pruebas y acciones comunes preconfiguradas, y es muy fácil agregar la suya (con solo configuración XML, no se necesita código nuevo para hacer esto).
Como una pequeña ventaja, cada una de estas pruebas y acciones está configurada para cada "dialecto" de SQL (así que, por ejemplo, puede tener un dialecto "oracle" y un dialecto "mySQL"). Esto significa que una vez que define las consultas para las pruebas y acciones dadas para cada dialecto, cada nueva instancia de una prueba o acción no requiere un nuevo SQL, y puede ejecutarse contra múltiples bases de datos de destino.
Luego, solo mantiene un pequeño archivo XML que enumera las pruebas y las acciones correspondientes, y ejecuta la herramienta contra su base de datos después de cada compilación.
Funciona bastante bien para nosotros.
Esto es lo que hacemos:
$ find src/sql/ | grep -v /.svn
src/sql/
src/sql/0000-system.sql
src/sql/0000-system.sql.dev.log
src/sql/0000-system.sql.prod.log
src/sql/0000-system.sql.test.log
src/sql/0001-usgn.sql
src/sql/0001-usgn.sql.dev.log
src/sql/0001-usgn.sql.prod.log
src/sql/0001-usgn.sql.test.log
src/sql/0002-usgn.sql
src/sql/0002-usgn.sql.dev.log
src/sql/0002-usgn.sql.prod.log
src/sql/0002-usgn.sql.test.log
src/sql/0003-usgn.sql
src/sql/0003-usgn.sql.dev.log
src/sql/0003-usgn.sql.prod.log
src/sql/0003-usgn.sql.test.log
src/sql/0004-system.sql
src/sql/0004-system.sql.dev.log
src/sql/0005-usgn.sql
src/sql/purge.sql
tenemos scriptseq ### - databaseusercredential.sql
Ahora nuestras pruebas, siempre permiten el estado de inicio desconocido de los datos en la base de datos. Si no puede hacer eso, le sugiero que use SEQ-CRED-TYPE.sql, donde el tipo sería dml / ddl y filtrar los scripts dml.
Un póster anterior incluía a Liquibase como opción, sin embargo, no mencionaron la capacidad de Liquibase para definir reglas que se ejecutan en contextos particulares ( Contexts in Liquibase ). Esto le permite tener las actualizaciones de esquema no marcadas con un contexto particular y los accesorios para las pruebas unitarias marcadas como contexto de test
. De esta forma, los accesorios solo se insertarán cuando ejecutes tus pruebas unitarias.
Aquí hay un ejemplo de un conjunto de cambios de Liquibase que contiene el esquema y los accesorios:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
<changeSet author="avalade" id="1">
<createTable tableName="users">
<column autoIncrement="true" name="id" type="long">
<constraints nullable="false" primaryKey="true" />
</column>
<column name="email" type="varchar(255)" />
</createTable>
</changeSet>
<changeSet author="avalade" id="2" context="test">
<insert tableName="user">
<column name="id" value="1" />
<column name="email" value="[email protected]" />
</insert>
</changeSet>
</databaseChangeLog>
Luego, si está usando Spring para administrar sus DAO, puede poner lo siguiente en su archivo de contexto de aplicación que está implementando:
<bean id="liquibase" class="liquibase.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:dbChangelog.xml" />
</bean>
Para el archivo de contexto de aplicación que usa en las pruebas de su unidad, configure Liquibase con una propiedad de contexto adicional:
<bean id="liquibase" class="liquibase.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:dbChangelog.xml" />
<property name="contexts" value="test" />
</bean>
De esta forma, puede mantener todas sus definiciones de base de datos juntas en un solo lugar y solo insertar sus accesorios cuando está ejecutando su código de prueba.