Murabei disponibiliza image de PostgresDB regenerativo para unit-test

Um dos principais problemas para a criação de sistemas de ciência de dados é a criação de bases de teste, estas correspondem à muitas entradas e as formas tradicionais que envolvem a utilização de fixtures or roll-backs passam a ser muito trabalhosas, A Murabei DS desenvolveu uma imagem docker com um banco de dados Postgres12 com extensão Timescale que tem seus dados regenerados após uma chamada get no end-point /reload-db/.

A base de dados regen-timescale-db regenera para os dados originais quando chamada em /reload-db/

Essa imagem é fruto de desenvolvimento interno da Murabei DS e é utilizada hoje no desenvolvimento de testes para o PUMPWOOD. Seu código é baseado na imagem postgres e timescale-db e está disponível no DockerHub e no Github.

A possibilidade de regenerar a base de dados utilizando uma chamada API facilita a utilização da imagem para o desenvolvimento de micro serviços e permite que possam ser criadas imagens com dados diferentes para testes específicos. Segue abaixo alguns exemplos de utilização:

 

1º passo: dump da base de dados

A 1a coisa a ser feita é o dump da base de dados que será utilizada para os testes.

PGPASSWORD=is_very_nice! pg_dump --disable-triggers -h localhost -p 5432 -U murabei --superuser murabei > database.sql

2º passo: build da imagem regen

A 2a coisa é fazer o build da imagem usando o dump da base de dados, segue um exemplo do DockerFile:

FROM andrebaceti/regen-timescale-db:0.0

############################################
# Use the same values of the dumped database
ENV POSTGRES_USER="murabei"
ENV POSTGRES_DB="murabei"
ENV POSTGRES_PASSWORD="is_very_nice!"

###############################################
# Name of the app, this will be used to set the
# regen end-point
ENV APP_NAME="regen-test"

#################################################################
# Copy the dumpfile to docker-entrypoint-initdb.d so
# the dumped database will be recriated when the container starts
COPY database/database.sql /docker-entrypoint-initdb.d/database.sql
RUN chmod 777 -R /docker-entrypoint-initdb.d/

3º passo: criar nosetests (ou coisa do tipo) usando a imagem

Para regenerar a base de dados é necessário chamar o end-point reload-db entre os testes ou mesmo durante os testes se for necessário. Segue abaixo um exemplo de unittest em Python, mas algo semelhante poderia ser programado em qualquer linguagem, basta chamar o end-point de regeneração.

"""Sets an example for nosetests using regen postgres image."""
import unittest
import requests
import pandas as pd
from sqlalchemy import create_engine


class TestExample(unittest.TestCase):
"""Unittest class that helps building pumpwood based systems test."""
  con_str = "postgresql://murabei:is_very_nice!@localhost/murabei"

  def setUp(self, *args, **kwargs):
    """Regen the database in the setUp calling reload end-point."""
    ######################
    # Regenerate database#
    for app in self.apps_to_regenerate:
      response = requests.get(
        "http://0.0.0.0:5000/reload-db/regen-test/")
    if response.status_code != 200:
      raise Exception(app + ' regenerate: ', response.text)

  def test__1(self):
    """Check if database has regen after call."""
    engine = create_engine(self.con_str)
    counts_start = pd.read_sql("""
      SELECT var, COUNT(*) AS count_start
      FROM data
      GROUP BY var
    """, con=engine)

    # Removing some rows...
    engine.execute("DELETE FROM data WHERE var='murabei'")
    counts_delete = pd.read_sql("""
      SELECT var, COUNT(*)
      FROM data
      GROUP BY var
    """, con=engine)
    self.assertNotIn('murabei', counts_delete["var"])

    # Regenerate database
    response = requests.get(
       "http://0.0.0.0:5000/reload-db/regen-test/")
    response.raise_for_status()

    # Check if database has regenerate
    counts_final = pd.read_sql("""
      SELECT var, COUNT(*) AS count_final
      FROM data
      GROUP BY var
    """, con=engine)
    pd_check_data = counts_final.merge(counts_start)
    check = (
      pd_check_data["count_final"] == pd_check_data[
      "count_start"]).all()
    self.assertTrue(check)

 

Feliz Natal comunidade!

Essa imagem é muito últil para o desenvolvimento de sistemas em microserviços onde mais de um pode modificar a base de dados e facilita no teste de migrações, permitindo o rollback. Outra facilidade é ser possível versionar facilmente as bases de testes usando as imagens docker. O código está licenciado em MIT License.

Feliz natal comunidade! A Murabei DS acredita no desenvolvimento colaborativo com a partcipação da comunidade, parceiros e universidade. Afinal, o que seria da ciência de dados sem tantas tecnologias open-source… Python, R, Flask, Django, ScikitLearn, pandas, timescaleDB, Postgres, NGINX… tem tantas que não cabe aqui no post.

 

Links

https://hub.docker.com/repository/docker/andrebaceti/regen-timescale-db

https://github.com/andrebaceti/regen-timescale-db