Envisagez de démarrer le conteneur Docker avant d'exécuter le test Pytest. Les tests d'intégration avec les middlewares périphériques peuvent être facilement exécutés, et il y a un avantage que l'environnement, les données de test et l'égalité peuvent être obtenus.
Par exemple, démarrez le conteneur PostgreSQL au moment de l'exécution du test et essayez d'entrer des données.
Avant l'exemple de code, considérez les restrictions d'utilisation du conteneur Docker ** dans le test unitaire.
--Le démon Docker doit être en cours d'exécution
-> Naturellement, mais important. Un obstacle de plus pour les cas où vous souhaitez effectuer un test dans un conteneur (?)
--Il semble que vous puissiez le faire en créant un conteneur qui peut faire Docker dans Docker (non vérifié).
Référence: Docker in Docker Better Practice
Vous devez attendre que le conteneur démarre
Le conteneur lui-même démarre rapidement, mais il faut souvent quelques secondes pour que le processus interne se termine et ** devienne disponible.
À mesure que le nombre de fonctions de test augmente, le temps d'exécution de tous les cas de test augmentera considérablement. ――Il est préférable d'utiliser une image de conteneur aussi légère que possible.
** Surveillez la sortie standard du conteneur et prévoyez d'attendre correctement jusqu'à ce qu'il soit prêt **
--pytest: test unitaire --docker: wrapper d'API Docker - docker --PyPI
$ pip install docker pytest SQLAlchemy psycopg2-binary
├── main.py
├── models.py
└── tests
├── __init__.py
├── conftest.py
└── test_main.py
models.py
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Staff(Base):
__tablename__ = 'staff'
id = Column(Integer, primary_key=True)
name = Column(String)
main.py
from sqlalchemy.orm import Session
from models import Staff
def add_staff(engine, name):
session = Session(bind=engine)
staff = Staff()
staff.name = name
session.add(staff)
session.commit()
Le but est de faire du moteur de SQL Alchemy un accessoire pour qu'il puisse être utilisé dans les fonctions de test.
tests/conftest.py
import time
import pytest
import docker
from sqlalchemy import create_engine
@pytest.fixture()
def pg_conf():
"""Gérer les paramètres PostgreSQL"""
host = '127.0.0.1'
port = 5432
dbname = 'pytest'
user = 'testuser'
password = 'test'
pg_conf = {'host': host,
'port': port,
'dbname': dbname,
'user': user,
'password': password,
'url': f'postgresql://{user}:{password}@{host}/{dbname}'}
return pg_conf
@pytest.fixture()
def engine(pg_conf):
return create_engine(pg_conf['url'])
@pytest.fixture(autouse=True)
def pg_container(pg_conf):
"""Démarrez le conteneur PostgreSQL"""
client = docker.from_env()
container = client.containers.run(image='postgres:11.6-alpine',
tty=True,
detach=True,
auto_remove=True,
environment={'POSTGRES_DB': pg_conf['dbname'],
'POSTGRES_USER': pg_conf['user'],
'POSTGRES_PASSWORD': pg_conf['password']},
ports={pg_conf['port']: '5432'})
#Attendez que le conteneur soit prêt
while True:
log = container.logs(tail=1)
if 'database system is ready to accept connections' in log.decode():
break
time.sleep(0.5)
yield #Transition à tester ici
container.kill()
Je vérifie la sortie standard dans le conteneur, mais une erreur se produit lorsque l'intervalle d'attente est trop court (0,4 seconde ou moins). Il semble préférable d'avoir un temps d'attente avec un peu de grâce.
test_main.py
from sqlalchemy.orm import Session
from models import Base, Staff
from main import add_staff
def test_add(engine):
#Ajouter 1 enregistrement
Base.metadata.create_all(bind=engine) #Créer une table
add_staff(engine=engine,
name='alice')
#Vérifiez l'enregistrement ajouté
session = Session(bind=engine)
assert session.query(Staff.id).filter_by(name='alice').first() == (1,)
session.close()
$ pytest --setup-show tests/ -v -s
========================================= test session starts =========================================platform linux -- Python 3.8.1, pytest-5.3.3, py-1.8.1, pluggy-0.13.1 -- /home/skokado/.local/share/virtualenvs/sandbox-pTebjwBw/bin/python3.8
cachedir: .pytest_cache
rootdir: ***
collected 1 item
tests/test_pg.py::test_add
SETUP F pg_conf
SETUP F pg_container (fixtures used: pg_conf)
SETUP F engine (fixtures used: pg_conf)
tests/test_main.py::test_add (fixtures used: engine, pg_conf, pg_container)PASSED
TEARDOWN F engine
TEARDOWN F pg_container
TEARDOWN F pg_conf
========================================== 1 passed in 2.00s ==========================================
Recommended Posts