Ich möchte einfach einen Komponententest einer Python-Anwendung mithilfe einer Datenbank mit pytest ausführen, ohne von der Umgebung beeinflusst zu werden. (Diejenigen, die als Daemon anstelle von Dateien wie SQLite3 gestartet werden)
Beispielcode: https://github.com/hkato/pytest-docker-mysql-example
Starten Sie MySQL von pytest auf Docker, geben Sie das Schema und die Testdaten ein und führen Sie den Test aus. Wenn Sie Docker-Compose festlegen und SQL in Bezug auf Docker-Entrypoint-Initdb.d unterstützen, sollte dies für andere Datenbanken wie PostgreSQL grundsätzlich identisch sein. (Der Initialisierungsmechanismus in docker-entrypoint-initdb.d sollte für offizielle MySQL / PostgreSQL-Container identisch sein, aber ich weiß nichts anderes.)
In Bezug auf pytest habe ich Docker gestartet und mir das Plug-In angesehen, das die Datenbank verwaltet, aber pytest-docker ist der Wartungsstatus und meine Nutzung / Umgebung Sieht gut aus für. pytest-dotenv wurde von Docker und pytest verwendet, um Umgebungsvariablen in ENV-Dateien zu beschreiben und sie gemeinsam zu machen.
Als Ergebnis einer anderen Überlegung als Pytest-Docker
Immerhin scheint pytest-docker das Beste zu sein, da es den Container der Webanwendung wie im offiziellen Dokument beschrieben verwenden kann und unabhängig von der Datenbank für allgemeine Zwecke verwendet werden kann ([MinIO-Container starten und AWS S3 ersetzen](https :: //qiita.com/hkato/items/89e436300c50c46624b9) Ich denke auch darüber nach.
.
├── src #Anwendungscode
│ └── *.py
├── tests #Testcode
│ ├── conftest.py
│ └── test_*.py
├── initdb.d #Datenbankschema & Testdaten usw.
│ ├── *.sql
│ └── *.sh
├── pytest.ini #pytest Einstellungen
├── .env #Einstellungen für Umgebungsvariablen
└── docker-compose.yml #Docker-Einstellungen
conftest.py
Standardmäßig verweist pytest-docker unter "tests /" auf "docker-compose.yml". Wenn Sie es direkt unter dem Projekt festlegen (geben Sie im Beispiel in README.md von pytest-docker ein anderes Verzeichnis oder einen anderen Dateinamen an), führen Sie bei Webanwendungen usw. die Datenbank mit "docker-compose up -d" aus Sie können einen Web-App-Server mit Gunicorn, uWSGI, Uvicorn usw. ausführen und debuggen (ich schließe dies aus, da dies nicht die Essenz dieser Zeit ist).
In der pytest-docker-Dokumentation wird es als Beispiel beschrieben, das einen httpbin REST-API-Container startet und auf 200 Antworten von Port 80 wartet. Im Fall von MySQL wurde entschieden, dass die Verbindung mit PyMySQL wie unten gezeigt hergestellt wurde und keine Ausnahme zurückgegeben wurde, dh der Docker-Container wurde gestartet und die anfänglichen Daten wurden eingegeben.
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
Warten Sie mit einem Timeout von 30 Sekunden in einem Zyklus von 0,1 Sekunden auf das oben Gesagte.
@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
Grundeinstellung der Python-Umgebung
$ #Im tatsächlichen Betrieb ist es möglicherweise besser, Pipenv oder Poetry für die Testumgebung und die Ausführungsumgebung zu verwenden.
$ python -m venv .venv
$ source .venv/bin/activate
$ pip install -r requirements.txt
Einstellungen für Umgebungsvariablen
$ cat << 'EOF' > .env
MYSQL_ROOT_PASSWORD='p@ssw0rd'
MYSQL_DATABASE='mydb'
MYSQL_USER='foo'
MYSQL_PASSWORD='pa$$Word'
EOF
Wenn der Test ausgeführt wird, wird der Docker-Container von Fixture gestartet, und der eigentliche Komponententest wird ausgeführt, nachdem SQL- und Shell-Skripte durch den Mechanismus von docker-entrypoint-initdb.d im Container angewendet wurden.
$ 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 ==============================
--pytest-docker ist praktisch, da Sie mit Docker Dienste starten können, die von Tests und nicht nur von Datenbanken abhängen.