Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aula 10 - Testes com postgres usam o mesmo banco usado para rodar app e apaga tabelas #158

Closed
lbmendes opened this issue May 30, 2024 · 5 comments

Comments

@lbmendes
Copy link
Contributor

Na seção final "Executando os testes no PostgreSQL" está setado para usar o mesmo banco setado na .env DATABASE_URL que também é usado para rodar o app. Esta situação tem algumas implicações, mas a implicação grave é que os testes estão rodando um drop_all que deleta as tabelas. Se vc rodar um teste e em seguida tentar rodar a aplicação o banco vai dar erro pois não vai encontrar as tabelas users e todo.
Para fazer funcionar eu entrei no container e rodei novamente os comandos do alembic:

# entrar numa sessão bash no container
docker exec -it fast_zero-fastzero_app-1 bash

# A partir daqui são comandos dentro do container
# Verificar situação quebrada do banco
alembic check

# Regera código das tabelas
alembic revision --autogenerate -m "corrige bug de exclusao das tabelas"
# aplica ajuste
alembic upgrade head

Uma ideia que pode ser usada é subir um container separado postgres só para os testes usando outra porta tipo 5433. Este container nem precisaria montar volume.

@lbmendes
Copy link
Contributor Author

Proposta de solução que testei aqui e funcionou legal. Trata-se de usar um outro database na mesma instância de postgres que já roda no docker compose:

  1. Com o banco do docker compose rodando, adicionar um novo database de nome test nele:
docker exec -it fast_zero-fastzero_database-1 psql -c 'create database test;' postgresql://app_user:app_password@localhost:5432/app_db
  1. Fazer os ajustes a seguir no tests/conftest.py para substituir o nome do banco para test na string de conexão ao banco:
 @pytest.fixture()
 def session():
-    engine = create_engine(Settings().DATABASE_URL)
+    DATABASE_URL = Settings().DATABASE_URL
+    TEST_DB = 'test'
+    TEST_DATABASE_URL = DATABASE_URL[:DATABASE_URL.rfind('/')] + '/' + TEST_DB
+    engine = create_engine(TEST_DATABASE_URL)
     table_registry.metadata.create_all(engine)
  1. Rodar comando de docker compose com --build para ele atualizar a imagem com as alterações

A partir daqui os testes podem rodar de boa sem atrapalhar o database principal (app_db)

@dunossauro
Copy link
Owner

dunossauro commented Jun 1, 2024

@lbmendes esse banco que estamos usando na aula 10 é o banco de desenvolvimento. Não tem problema ele ser apagado. O banco de produção será criado na próxima aula (12)

@dunossauro
Copy link
Owner

Estava pensando em criar uma substituição para o testcontainers para não precisar subir o postgres para rodar os testes com docker:

diff --git a/codigo_das_aulas/10/tests/conftest.py b/codigo_das_aulas/10/tests/conftest.py
index d063b7f..1e4c460 100644
--- a/codigo_das_aulas/10/tests/conftest.py
+++ b/codigo_das_aulas/10/tests/conftest.py
@@ -2,15 +2,25 @@ import pytest
 from fastapi.testclient import TestClient
 from sqlalchemy import create_engine
 from sqlalchemy.orm import Session
+from testcontainers.postgres import PostgresContainer
 
 from fast_zero.app import app
 from fast_zero.database import get_session
 from fast_zero.models import table_registry
 from fast_zero.security import get_password_hash
-from fast_zero.settings import Settings
 from tests.factories import UserFactory
 
 
+@pytest.fixture(scope='session')
+def engine():
+    with PostgresContainer("postgres:16", driver='psycopg') as p:
+
+        _engine = create_engine(p.get_connection_url())
+
+        with _engine.begin():
+            yield _engine
+
+
 @pytest.fixture()
 def client(session):
     def get_session_override():
@@ -24,8 +34,7 @@ def client(session):
 
 
 @pytest.fixture()
-def session():
-    engine = create_engine(Settings().DATABASE_URL)
+def session(engine):
     table_registry.metadata.create_all(engine)
 
     with Session(engine) as session:

@dunossauro
Copy link
Owner

Fechado por #162

@lbmendes
Copy link
Contributor Author

lbmendes commented Jun 7, 2024

Ficou muito legal com testcontainers, não conhecia e achei muito bom! Valeu Duno!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants