[PYTHON] Exemple d'environnement pytest pour réparer la base de données avec Docker

Objectif

Je souhaite exécuter facilement un test unitaire d'une application Python à l'aide d'une base de données avec pytest sans être affecté par l'environnement. (Ceux qui démarrent en tant que démon au lieu de fichiers tels que SQLite3)

Ce qui a été fait

Exemple de code: https://github.com/hkato/pytest-docker-mysql-example

Lancez MySQL à partir de pytest sur Docker, entrez le schéma et les données de test, et exécutez le test. Si vous définissez docker-compose et que vous prenez en charge SQL lié à docker-entrypoint-initdb.d, il devrait en être de même pour les autres bases de données telles que PostgreSQL. (Le mécanisme d'initialisation dans docker-entrypoint-initdb.d devrait être le même pour les conteneurs officiels MySQL / PostgreSQL, mais je ne sais rien d'autre)

Environnement requis et plugin pytest

Concernant pytest, j'ai démarré Docker et regardé le plug-in qui gère la base de données, mais pytest-docker est le statut de maintenance et mon utilisation / environnement Ça a l'air bien pour. pytest-dotenv a été utilisé par Docker et pytest pour décrire les variables d'environnement dans les fichiers .env et les rendre communes.

Autres considérations

À la suite de considérations autres que pytest-docker

Après tout, pytest-docker semble être le meilleur car il peut utiliser le conteneur de l'application Web comme décrit dans le document officiel, et il peut être utilisé à des fins générales quelle que soit la base de données ([Démarrer le conteneur MinIO et remplacer AWS S3](https :: //qiita.com/hkato/items/89e436300c50c46624b9) Je pense le faire aussi).

Structure du répertoire

.
├── src                 #Code d'application
│   └── *.py
├── tests               #Code de test
│   ├── conftest.py
│   └── test_*.py
├── initdb.d            #Schéma de base de données et données de test, etc.
│   ├── *.sql
│   └── *.sh
├── pytest.ini          #paramètres pytest
├── .env                #Paramètres des variables d'environnement
└── docker-compose.yml  #Paramètres de Docker

Aperçu du code

conftest.py

Prise en charge du placement de docker-compose.yml

Par défaut, pytest-docker référence docker-compose.yml sous tests /. En définissant directement sous le projet (spécifiez un autre répertoire ou nom de fichier dans l'exemple dans README.md de pytest-docker), dans le cas des applications Web etc., exécutez la base de données avec docker-compose up -d Vous pouvez exécuter et déboguer un serveur d'applications Web avec Gunicorn, uWSGI, Uvicorn, etc. (j'exclus cela car ce n'est pas l'essence de cette fois).

Prend en charge l'attente du démarrage de MySQL

La documentation de pytest-docker le décrit comme un exemple de lancement d'un conteneur d'API REST httpbin et d'attente de 200 réponses du port 80. Dans le cas de MySQL, il a été décidé que la connexion était établie avec PyMySQL comme indiqué ci-dessous et aucune exception n'a été renvoyée, c'est-à-dire que le conteneur Docker a été démarré et que les données initiales ont été entrées.

def is_database_ready(docker_ip):
    try:
        pymysql.connect(
            host=docker_ip,
            user=os.getenv('MYSQL_USER', ''),
            password=os.getenv('MYSQL_PASSWORD', ''),
            db=os.getenv('MYSQL_DATABASE')
        )
        return True
    except:
        return False

Attendez ce qui précède avec un délai de 30 secondes dans un cycle de 0,1 seconde.

@pytest.fixture(scope="session")
def database_service(docker_ip, docker_services):
    docker_services.wait_until_responsive(
        timeout=30.0, pause=0.1, check=lambda: is_database_ready(docker_ip)
    )
    return

Résultat d'exécution

Configuration initiale de l'environnement Python

$ #En fonctionnement réel, il peut être préférable d'utiliser Pipenv ou Poetry pour l'environnement de test et l'environnement d'exécution.
$ python -m venv .venv
$ source .venv/bin/activate
$ pip install -r requirements.txt

Paramètres des variables d'environnement

$ cat << 'EOF' > .env
MYSQL_ROOT_PASSWORD='p@ssw0rd'
MYSQL_DATABASE='mydb'
MYSQL_USER='foo'
MYSQL_PASSWORD='pa$$Word'
EOF

Lorsque le test est exécuté, le conteneur Docker est démarré par Fixture, et le test unitaire réel est exécuté après que les scripts SQL et shell soient appliqués par le mécanisme de docker-entrypoint-initdb.d dans le conteneur.

$ pytest
============================= test session starts ==============================
platform darwin -- Python 3.8.6, pytest-6.1.2, py-1.9.0, pluggy-0.13.1 -- /Users/username/tmp/.venv/bin/python
cachedir: .pytest_cache
rootdir: /Users/username/tmp, configfile: pytest.ini
plugins: dotenv-0.5.2, cov-2.10.1, docker-0.10.1
collected 1 item                                                               

tests/test_users.py::test_get_name_by_id PASSED                          [100%]

---------- coverage: platform darwin, python 3.8.6-final-0 -----------
Name         Stmts   Miss  Cover
--------------------------------
src/app.py       8      0   100%


============================== 1 passed in 16.35s ==============================

Sommaire

--pytest-docker est pratique car vous pouvez lancer des services qui dépendent de tests, pas seulement de bases de données, avec Docker. --Il peut être bon de changer l'emplacement de docker-compose.yml de tests / directement sous le projet. Peut également être utilisé pour le débogage normal

Recommended Posts

Exemple d'environnement pytest pour réparer la base de données avec Docker
Préparer l'environnement d'exécution de Python3 avec Docker
Correction de la base de données avec pytest-docker
De Kafka à KSQL - Construction d'environnement facile avec docker
Préparation de l'environnement d'exécution de PyTorch avec Docker Novembre 2019
Ssh dans un environnement virtuel avec vscode Remote Development
Préparer l'environnement python3 avec Docker
Avantages et inconvénients de la conversion de l'environnement de développement de Django en Docker
De la construction de l'environnement au déploiement pour flask + Heroku avec Docker
Construire un environnement Mysql + Python avec docker
Comment utiliser Jupyter Notebook sans polluer votre environnement avec Docker
J'ai essayé de corriger "J'ai essayé la simulation probabiliste du jeu de bingo avec Python"
Reconstruisez l'environnement de développement de Django avec Docker! !! !! !!
Je voulais utiliser le notebook jupyter avec docker dans l'environnement pip (opticspy)
Préparer un environnement pour toucher les fichiers au format grib2 avec python (édition Docker)
Paramètre pour entrer le contenu de la bibliothèque avec pytest et effectuer un test de débogage
Maintenance de l'environnement réalisée avec Docker (je souhaite post-traiter GrADS en Python
Résumé de la création d'un environnement LAMP + Wordpress avec Sakura VPS
Changer l'environnement Python 64 bits en environnement 32 bits avec Anaconda
Comment créer un environnement NVIDIA Docker
Connectez-vous à MySQL avec Python dans Docker
Obtenez un environnement local pour DynamoDB avec Docker
Exemple de script pour afficher BoundingBox avec PIL
Créer un environnement Python + uWSGI + Nginx avec Docker
Essayez de préparer chaque environnement de kivy
[Linux] Créer un environnement Jenkins avec Docker
Environnement de lancement avec LineBot + Heroku + Docker + Python
Introduction à docker Création d'un environnement ubuntu dans ubuntu
Exemple de traitement efficace des données avec PANDAS
Construire un environnement de NGINX + NGINX Unit + MySQL avec Docker
Comment installer python3 avec docker centos
[Linux] Construction de l'environnement Docker avec Amazon Linux 2
J'ai essayé de créer un environnement Ubuntu 20.04 LTS + ROS2 avec Raspberry Pi 4
Un exemple de cloudbuild.yaml lors du déploiement automatique de Django sur App Engine avec Cloud Build
Ubuntu 16.04 LTS, mémorandum de construction d'environnement pour débutant pour changer la version d'Anaconda avec pyenv
Hello World avec gRPC / go dans l'environnement Docker
Construire un environnement d'analyse avec Docker (jupyter notebook + PostgreSQL)
Je veux moquer datetime.datetime.now () même avec pytest!
[Python] Créer un environnement de développement Django avec Docker
Utiliser plusieurs versions de l'environnement python avec pyenv
Exemple d'obtention d'un jeton d'accès de mastodonte avec code_autorisation
Créer un environnement de Nginx + uWSGI + Python (Django) avec docker
Script pour tweeter avec des multiples de 3 et des nombres avec 3 !!
Comment spécifier des attributs avec Mock of Python
Comment implémenter "named_scope" de RubyOnRails avec Django
Histoire d'essayer d'utiliser Tensorboard avec Pytorch
Construction d'environnement Poetry-virtualenv avec python de centos-sclo-rh ~ Notes
Impossible de se connecter à MySQL depuis l'environnement Docker (Debian)
Flux de création d'un environnement virtuel avec Anaconda
Envoyer msgpack avec ajax à l'environnement flask (werkzeug)
De la construction d'environnement Python à la construction d'environnement virtuel avec anaconda
Procédure de réglage de l'hydrogène de l'atome (environnement virtuel)
Exemple de lecture et d'écriture de CSV avec Python
Utiliser l'environnement virtuel d'anaconda avec Zsh (gestion des problèmes)
Comment démarrer avec Visual Studio Online ~ La fin de l'ère de la construction d'environnement ~