Estoy programando en Java y mis aplicaciones utilizan mucho DB. Por lo tanto, es importante para mí poder probar el uso de mi base de datos fácilmente.
¿De qué se tratan las pruebas de base de datos? Para mí, deberían proporcionar dos requisitos simples:
- Verifique la sintaxis SQL.
- Más importante aún, verifique que los datos estén seleccionados / actualizados / insertados correctamente, de acuerdo con una situación dada.
Bueno, parece que todo lo que necesito es una base de datos.
Pero en realidad, prefiero no, ya que hay pocas dificultades para usar una base de datos para una prueba:
- "Consiga una base de datos de prueba, ¿qué tan difícil podría ser?" - Bueno, en mi lugar de trabajo, tener un DB de prueba personal es bastante imposible. Tienes que utilizar una base de datos "pública", que sea accesible para todos.
- "Estas pruebas no son rápidas ..." - Las pruebas de DB tienden a ser más lentas que las pruebas habituales. Realmente no es ideal tener pruebas lentas.
- "¡Este programa debería manejar cualquier caso!" - Se vuelve algo molesto e incluso imposible intentar simular todos y cada uno de los casos en una base de datos. Para cada caso, se debe realizar una cierta cantidad de consultas de inserción / actualización, lo cual es molesto y lleva tiempo.
- "Espera un segundo, ¿cómo sabes que hay 542 filas en esa tabla?" - Uno de los principios fundamentales en las pruebas es poder probar la funcionalidad de una manera diferente a la de su código probado. Cuando se usa una base de datos, generalmente hay una forma de hacer algo, por lo tanto, la prueba es exactamente la misma que el código central.
Entonces, puede darse cuenta de que no me gustan las bases de datos cuando se trata de pruebas (por supuesto, tendré que llegar a esto en algún momento, pero prefiero llegar más tarde en mis pruebas, después de encontrar la mayoría de los errores usando el resto de los métodos de prueba). ¿Pero qué estoy buscando?
Estoy buscando una forma de simular una base de datos, una base de datos simulada, usando el sistema de archivos o simplemente la memoria virtual. Pensé que tal vez hay una herramienta / paquete Java que permite simplemente construir (usando la interfaz de código) un simulacro de base de datos por prueba, con tablas y filas simuladas, con verificación de SQL y con una interfaz de código para monitorear su estado (en lugar de usar SQL ).
¿Está familiarizado con este tipo de herramienta?
Editar: ¡ Gracias por las respuestas! Aunque estaba pidiendo una herramienta, también me brindó algunos consejos sobre el problema :) Me llevará algún tiempo revisar sus ofertas, así que no puedo decir ahora si sus respuestas fueron satisfactorias o no.
De todos modos, aquí hay una mejor vista de lo que estoy buscando: imagina una clase llamada DBMonitor, que una de sus características es encontrar el número de filas en una tabla. Aquí hay un código imaginario de cómo me gustaría probar esa característica usando JUnit:
public class TestDBMonitor extends TestCase {
@Override
public void setUp() throws Exception {
MockConnection connection = new MockConnection();
this.tableName = "table1";
MockTable table = new MockTable(tableName);
String columnName = "column1";
ColumnType columnType = ColumnType.NUMBER;
int columnSize = 50;
MockColumn column = new MockColumn(columnName, columnType, columnSize);
table.addColumn(column);
for (int i = 0; i < 20; i++) {
HashMap<MockColumn, Object> fields = new HashMap<MockColumn, Object>();
fields.put(column, i);
table.addRow(fields);
}
this.connection = connection;
}
@Test
public void testGatherStatistics() throws Exception {
DBMonitor monitor = new DBMonitor(connection);
monitor.gatherStatistics();
assertEquals(((MockConnection) connection).getNumberOfRows(tableName),
monitor.getNumberOfRows(tableName));
}
String tableName;
Connection connection;
}
Espero que este código sea lo suficientemente claro para entender mi idea (disculpe los errores de sintaxis, estaba escribiendo manualmente sin mi querido Eclipse: P).
Por cierto, utilizo ORM parcialmente y mis consultas SQL sin procesar son bastante simples y no deberían diferir de una plataforma a otra.
Java viene con Java DB .
Dicho esto, desaconsejaría usar un tipo de base de datos diferente al que usa en producción a menos que pase por una capa ORM. De lo contrario, es posible que su SQL no sea tan multiplataforma como cree.
También echa un vistazo a DbUnit
fuente
He usado Hypersonic para este propósito. Básicamente, es un archivo JAR (una base de datos Java pura en memoria) que puede ejecutar en su propia JVM o en su propia JVM y mientras se está ejecutando, tiene una base de datos. Luego lo detiene y su base de datos desaparece. Lo he usado, hasta ahora, como una base de datos puramente en memoria. Es muy sencillo iniciar y detener a través de Ant cuando se ejecutan pruebas unitarias.
fuente
Hay muchos puntos de vista sobre cómo probar los puntos de integración, como la conexión de la base de datos a través de SQL. Mi conjunto personal de reglas que me ha funcionado bien es el siguiente:
1) Separe la lógica y las funciones de acceso a la base de datos de la lógica empresarial general y ocúltela detrás de una interfaz. Razón: Para probar la gran mayoría de la lógica en el sistema, es mejor usar un código ficticio / stub en lugar de la base de datos real, ya que es más simple. Razón 2: es dramáticamente más rápido
2) Trate las pruebas para la base de datos como pruebas de integración que están separadas del cuerpo principal de las pruebas unitarias y necesitan ejecutarse en una base de datos de configuración Razón: Velocidad y calidad de las pruebas
3) Cada desarrollador necesitará su propia base de datos distinta. Necesitarán una forma automatizada de actualizar su estructura en función de los cambios de sus compañeros de equipo e introducir datos. Ver puntos 4 y 5.
4) Utilice una herramienta como http://www.liquibase.org para administrar las actualizaciones en la estructura de su base de datos. Razón: le da agilidad en la capacidad de cambiar la estructura existente y avanzar en versiones
5) Utilice una herramienta como http://dbunit.sourceforge.net/ para administrar los datos. Configure archivos de escenario (xml o XLS) para casos de prueba particulares y datos base y solo aclare lo que se necesita para cada caso de prueba. Razón: mucho mejor que insertar y eliminar datos manualmente Razón 2: más fácil para los evaluadores entender cómo ajustar los escenarios Razón 3: es más rápido ejecutar esto
6) Necesita pruebas funcionales que también tengan DBUnit como datos de escenario, pero estos son conjuntos de datos mucho más grandes y ejecutan todo el sistema. Esto completa el paso de combinar el conocimiento de que a) Las pruebas unitarias se ejecutan y, por lo tanto, la lógica es sólida b) Que las pruebas de integración en la base de datos se ejecutan y SQL es correcto, lo que da como resultado "y el sistema en su conjunto funciona en conjunto como un pila inferior "
Esta combinación me ha servido bien hasta ahora para lograr una alta calidad en las pruebas y el producto, así como para mantener la velocidad del desarrollo de las pruebas unitarias y la agilidad para cambiar.
fuente
Parece que tiene problemas culturales en el trabajo que le están proporcionando una barrera para poder hacer su trabajo al máximo de sus capacidades y el beneficio de su producto. Es posible que desee hacer algo al respecto.
Por otro lado, si el esquema de su base de datos está bajo control de versiones, siempre puede tener una compilación de prueba que cree una base de datos a partir del esquema, la llene con datos de prueba, ejecute sus pruebas, recopile los resultados y luego descarte la base de datos. Solo existirá mientras duren las pruebas. Puede ser una nueva base de datos en una instalación existente si el hardware es un problema. Esto es similar a lo que hacemos donde trabajo.
fuente
Si está utilizando Oracle en el trabajo, puede utilizar la función Punto de restauración en la base de datos Flashback para que la base de datos vuelva a un momento anterior a sus pruebas. Esto eliminará cualquier cambio que haya realizado personalmente en la base de datos.
Ver:
https://docs.oracle.com/cd/E11882_01/backup.112/e10642/flashdb.htm#BRADV71000
Si necesita una base de datos de prueba para su uso con la producción / trabajo de Oracle, busque la base de datos XE, edición express de Oracle. Esto es gratuito para uso personal, con un límite de base de datos de menos de 2 GB.
fuente
Recientemente cambiamos a JavaDB o Derby para implementar esto. Derby 10.5.1.1 ahora implementa una representación en memoria para que se ejecute muy rápido, no necesita ir al disco: Derby In Memory Primer
Diseñamos nuestra aplicación para que se ejecute en Oracle, PostgreSQL y Derby, de modo que no avancemos demasiado en ninguna plataforma antes de descubrir que una base de datos admite una función que otras no.
fuente
Estoy de acuerdo con banjollity. La configuración de entornos de prueba y desarrollo aislados debe ser una prioridad. Cada sistema de base de datos que he usado es de código abierto o tiene una edición gratuita para desarrolladores que puede instalar en su estación de trabajo local. Esto le permite desarrollar con el mismo dialecto de base de datos que la producción, le brinda acceso de administrador completo a las bases de datos de desarrollo y es más rápido que usar un servidor remoto.
fuente
Intenta usar derby . Es fácil y portátil. Con Hibernate, su aplicación se vuelve flexible. Prueba en el derbi, producción en cualquier cosa que te guste y confíes.
fuente
Estamos creando un entorno de prueba de base de datos en funcionamiento en este momento. Creemos que debemos utilizar un sistema de gestión de base de datos real con datos simulados . Un problema con un DBMS simulado es que SQL nunca se consolidó totalmente como estándar, por lo que un entorno de prueba artificial tendría que respaldar fielmente el dialecto de nuestra base de datos de producción. Otro problema es que hacemos un uso extensivo de restricciones de valor de columna, restricciones de clave externa y restricciones únicas, y dado que una herramienta artificial probablemente no las implementaría, nuestras pruebas unitarias podrían pasar, pero las pruebas de nuestro sistema fallarían cuando llegaran por primera vez a lo real. limitaciones. Si las pruebas tardan demasiado, esto indica un error de implementación y ajustamos nuestras consultas (por lo general, los conjuntos de datos de prueba son minúsculos en comparación con la producción).
Hemos instalado un DBMS real en cada máquina de desarrollo y en nuestro servidor de prueba e integración continua (usamos Hudson). No sé cuáles son las restricciones de su política de trabajo, pero es bastante fácil de instalar y usar PostgreSQL, MySQL y Oracle XE. Todos son gratuitos para su uso en desarrollo (incluso Oracle XE), por lo que no hay ninguna razón racional para prohibir su uso.
La cuestión clave es ¿cómo garantizar que sus pruebas siempre comiencen con la base de datos en un estado coherente? Si todas las pruebas fueran de solo lectura, no hay problema. Si pudiera diseñar pruebas mutantes para que siempre se ejecuten en transacciones que nunca se confirman, no hay problema. Pero normalmente debe preocuparse por revertir las actualizaciones. Para hacer esto, puede exportar el estado inicial a un archivo, luego volver a importarlo después de la prueba (los comandos exp e imp shell de Oracle hacen esto). O puede usar un punto de control / retroceso. Pero una forma más elegante es usar una herramienta como dbunit , que nos funciona bien.
La ventaja clave de esto es que detectamos muchos más errores desde el principio, donde son mucho más fáciles de corregir y nuestras pruebas del sistema real no se bloquean mientras los desarrolladores intentan febrilmente depurar problemas. Esto significa que producimos mejor código más rápido y con menos esfuerzo.
fuente
Puede utilizar HSQLDB para realizar pruebas en la base de datos de la memoria. Iniciar la base de datos en memoria y ejecutar pruebas en ella es bastante sencillo.
http://hsqldb.org/
fuente
jOOQ es una herramienta que además de ofrecer abstracción SQL también tiene pequeñas herramientas integradas como un SPI que permite burlarse de la totalidad de JDBC. Esto puede funcionar de dos maneras, como se documenta en esta publicación de blog. :
Al implementar el
MockDataProvider
SPI:// context contains the SQL string and bind variables, etc. MockDataProvider provider = context -> { // This defines the update counts, result sets, etc. // depending on the context above. return new MockResult[] { ... } };
En la implementación anterior, puede interceptar programáticamente cada declaración SQL y devolver un resultado para ella, incluso dinámicamente "analizando" la cadena SQL para extraer algunos predicados / información de tabla, etc.
Usando el más simple (pero menos poderoso)
MockFileDatabase
... que tiene un formato como el siguiente (un conjunto de pares de declaración / resultado):
El archivo anterior se puede leer y consumir de la siguiente manera:
import static java.lang.System.out; import java.sql.*; import org.jooq.tools.jdbc.*; public class Mocking { public static void main(String[] args) throws Exception { MockDataProvider db = new MockFileDatabase( Mocking.class.getResourceAsStream("/mocking.txt"); try (Connection c = new MockConnection(db)); Statement s = c.createStatement()) { out.println("Actors:"); out.println("-------"); try (ResultSet rs = s.executeQuery( "select first_name, last_name from actor")) { while (rs.next()) out.println(rs.getString(1) + " " + rs.getString(2)); } } } }
Observe cómo estamos usando la API JDBC directamente, sin conectarnos a ninguna base de datos.
Tenga en cuenta que trabajo para el proveedor de jOOQ, por lo que esta respuesta está sesgada.
Tenga cuidado, en algún momento, está implementando una base de datos completa
Lo anterior funciona para casos simples. Pero tenga en cuenta que, eventualmente, implementará una base de datos completa. Usted quiere:
Bien, burlándose de la base de datos como se muestra arriba, puede "verificar" la sintaxis, porque cada sintaxis que no haya previsto en la versión exacta que se enumera arriba será rechazada por cualquier enfoque burlón.
Puede implementar un analizador que analice SQL ( o, nuevamente, usar jOOQ ) y luego transformar la declaración SQL en algo que pueda reconocer más fácilmente y producir un resultado. Pero en última instancia, esto solo significa implementar una base de datos completa.
Esto dificulta aún más las cosas. Si ejecuta una inserción y luego actualiza, el resultado es obviamente diferente de actualizar primero, luego insertar, ya que la actualización puede o no afectar la fila insertada.
¿Cómo se asegura de que esto suceda cuando se "burla" de una base de datos? Necesita una máquina de estado que recuerde el estado de cada tabla "simulada". En otras palabras, implementará una base de datos.
Burlarse solo te llevará hasta aquí
Como mencionó Piotrek , burlarse solo te llevará hasta aquí. Es útil en casos simples cuando necesita interceptar solo unas pocas consultas muy conocidas. Es imposible, si quiere simular la base de datos de un sistema completo. En ese caso, use una base de datos real, idealmente el mismo producto que está usando en producción.
fuente
Creo que mi marco Acolyte se puede usar para dicha maqueta de base de datos: https://github.com/cchantep/acolyte .
Permite ejecutar Java existente (para pruebas) con conexiones que usted maneja para consultar / actualizar: devolver los conjuntos de resultados apropiados, actualizar el recuento o advertir según los casos de ejecución.
fuente
Bueno, para empezar, ¿está utilizando alguna capa ORM para el acceso a la base de datos?
Si no es así: entonces lo que está pensando no sería de utilidad. ¿De qué sirve probar cuando no está seguro de que el SQL que está disparando funcionará con su base de datos en producción, ya que en los casos de prueba está usando otra cosa?
En caso afirmativo: entonces puede ver varias opciones señaladas.
fuente