Advertisement
  1. Code
  2. Go

Prueba de código intensivo de datos con Go, parte 2

Scroll to top
Read Time: 10 min
This post is part of a series called Testing Data-Intensive Code with Go.
Testing Data-Intensive Code With Go, Part 1
Testing Data-Intensive Code With Go, Part 3

Spanish (Español) translation by steven (you can also view the original English article)

Visión general

Esta es la segunda parte de cinco de una serie de tutoriales sobre cómo probar código con uso intensivo de datos. En la primera parte, cubrí el diseño de una capa de datos abstractos que permite realizar pruebas adecuadas, cómo manejar errores en la capa de datos, cómo simular el código de acceso a datos y cómo realizar pruebas con una capa de datos abstractos. En este tutorial, repasaré las pruebas con una capa de datos en memoria real basada en el popular SQLite.

Prueba contra un almacén de datos en memoria

Probar contra una capa de datos abstracta es excelente para algunos casos de uso en los que necesitas mucha precisión, comprende exactamente qué llamadas hará el código bajo prueba contra la capa de datos y estás de acuerdo con la preparación de las respuestas simuladas.

A veces, no es tan fácil. La serie de llamadas a la capa de datos puede ser difícil de calcular o se necesita mucho esfuerzo para preparar respuestas predefinidas que sean válidas. En estos casos, es posible que debas trabajar con un almacén de datos en memoria.

Los beneficios de un almacén de datos en memoria son:

  • Es muy rápido.
  • Trabajas contra un almacén de datos real.
  • A menudo, puedes completarlo desde cero utilizando archivos o código.

En particular, si tu almacén de datos es una base de datos relacional, SQLite es una opción fantástica. Solo recuerda que existen diferencias entre SQLite y otras bases de datos relacionales populares como MySQL y PostgreSQL.

Asegúrate de tenerlo en cuenta en tus pruebas. Ten en cuenta que aún puedes acceder a tus datos a través de la capa de datos abstractos, pero ahora el almacén de respaldo durante las pruebas es el almacén de datos en memoria. Tu prueba completará los datos de prueba de manera diferente, pero el código bajo prueba es felizmente inconsciente de lo que está sucediendo.

Usando SQLite

SQLite es una base de datos integrada (vinculada con tu aplicación). No se está ejecutando un servidor de base de datos independiente. Por lo general, almacena los datos en un archivo, pero también tiene la opción de un almacenamiento de respaldo en memoria.

Aquí está la estructura InMemoryDataStore. También es parte del paquete concrete_data_layer e importa el paquete de terceros go-sqlite3 que implementa la interfaz estándar "database/sql" de Golang.

Construcción de la capa de datos en memoria

La función constructora NewInMemoryDataLayer() crea una base de datos sqlite en memoria y devuelve un puntero al InMemoryDataLayer.

Ten en cuenta que cada vez que abres una nueva base de datos ":memory:", comienza desde cero. Si deseas persistencia en varias llamadas a NewInMemoryDataLayer(), debes usar file::memory:?cache=shared. Consulta este hilo de discusión de GitHub para obtener más detalles.

InMemoryDataLayer implementa la interfaz DataLayer y realmente almacena los datos con las relaciones correctas en tu base de datos sqlite. Para hacer eso, primero necesitamos crear un esquema adecuado, que es exactamente el trabajo de la función createSqliteSchema() en el constructor. Esto crea tres tablas de datos -song, user, y label- (canción, usuario y etiqueta) y dos tablas de referencias cruzadas, label_song y user_song.

Agrega algunas restricciones, índices y claves externas para relacionar las tablas entre sí. No me detendré en los detalles específicos. La esencia de esto es que todo el esquema DDL se declara como una sola cadena (que consta de múltiples declaraciones DDL) que luego se ejecutan utilizando el método db.Exec(), y si algo sale mal, devuelve un error.

Es importante darse cuenta de que, si bien SQL es estándar, cada sistema de administración de bases de datos (DBMS) tiene su propio sabor, y la definición exacta del esquema no necesariamente funcionará como está para otra base de datos.

Implementación de la capa de datos en memoria

Para darte una idea del esfuerzo de implementación de una capa de datos en memoria, aquí hay un par de métodos: AddSong() y GetSongsByUser().

El método AddSong() hace mucho trabajo. Inserta un registro en la tabla song, así como en cada una de las tablas de referencia: label_song y user_song. En cada punto, si alguna operación falla, solo devuelve un error. No utilizo ninguna transacción porque está diseñada solo con fines de prueba, y no me preocupo por los datos parciales en la base de datos.

GetSongsByUser() usa un join + sub-select de la referencia cruzada user_song para devolver canciones para un usuario específico. Utiliza los métodos Query() y luego escanea cada fila para completar una estructura Song del modelo de objeto de dominio y devolver una porción de canciones. La implementación de bajo nivel como base de datos relacional se oculta de forma segura.

Este es un gran ejemplo de cómo utilizar una base de datos relacional real como sqlite para implementar el almacén de datos en memoria en lugar de utilizar el nuestro, lo que requeriría mantener mapas y garantizar que toda la contabilidad sea correcta.

Ejecución de pruebas contra SQLite

Ahora que tenemos una capa de datos en memoria adecuada, echemos un vistazo a las pruebas. Coloqué estas pruebas en un paquete separado llamado sqlite_test, e importé localmente la capa de datos abstractos (el modelo de dominio), la capa de datos concretos (para crear la capa de datos en memoria) y el administrador de canciones (el código bajo prueba) . ¡También preparo dos canciones para las pruebas del sensacional artista panameño El Chombo!

Los métodos de prueba crean una nueva capa de datos en memoria para comenzar desde cero y ahora pueden llamar a métodos en la capa de datos para preparar el entorno de prueba. Cuando todo está configurado, pueden invocar los métodos del administrador de canciones y luego verificar que la capa de datos contiene el estado esperado.

Por ejemplo, el método de prueba AddSong_Success() crea un usuario, agrega una canción usando el método AddSong() del administrador de canciones y verifica que después de llamar a GetSongsByUser() se devuelve la canción agregada. Luego agrega otra canción y vuelve a verificar.

El método de prueba TestAddSong_Duplicate() es similar, pero en lugar de agregar una nueva canción la segunda vez, agrega la misma canción, lo que da como resultado un error de canción duplicada:

Conclusión

En este tutorial, implementamos una capa de datos en memoria basada en SQLite, llenamos una base de datos SQLite en memoria con datos de prueba y utilizamos la capa de datos en memoria para probar la aplicación.

En la tercera parte, nos centraremos en las pruebas contra una capa de datos compleja local que consta de varios almacenes de datos (una base de datos relacional y una caché de Redis). Mantente al tanto.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.