Einleitung: Warum Integrationstests von PHP in Docker ein Muss sind
Die moderne PHP-Anwendungsentwicklung beschränkt sich selten auf einen einzelnen Server. Datenbanken, Caches (Redis, Memcached), Warteschlangen (RabbitMQ), externe APIs – all dies erfordert die Überprüfung der Komponenteninteraktion. Unit-Tests isolieren den Code, garantieren jedoch nicht, dass Klasse A korrekt mit Klasse B über eine echte Datenbank zusammenarbeitet. Hier kommt Integrationstests zur Rettung.
Das Problem des klassischen Ansatzes ist die Einrichtung der Umgebung. Ein Entwickler verbringt Stunden damit, MySQL einzurichten, Berechtigungen zu konfigurieren und PHP-Erweiterungen zu installieren. Docker löst dieses Problem ein für alle Mal. In diesem Artikel werden wir untersuchen, wie man Integrationstests für eine PHP-Anwendung mit Docker und Docker Compose organisiert. Sie erhalten fertige Konfigurationen, Codebeispiele und Optimierungsempfehlungen.
1. Einrichten der Docker-Umgebung für PHP-Tests
1.1. Grundlegende Projektstruktur
Nehmen wir an, wir haben eine einfache PHP-Anwendung mit Symfony oder Laravel (jedes Framework funktioniert). Erstellen Sie eine docker-compose.yml-Datei im Projektstammverzeichnis:
version: '3.8'
services: php: build: . volumes: - .:/var/www/html environment: - DATABASE_URL=mysql://test_user:test_pass@db:3306/test_db depends_on: - db
db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root_pass MYSQL_DATABASE: test_db MYSQL_USER: test_user MYSQL_PASSWORD: test_pass ports: - "3307:3306" # Weiterleitung auf einen nicht standardmäßigen Port, um Konflikte mit der lokalen DB zu vermeiden
test_runner: image: php:8.2-cli volumes: - .:/var/www/html working_dir: /var/www/html entrypoint: ["vendor/bin/phpunit"] depends_on: - db - phpWichtige Punkte:
- Der Dienst
test_runnerverwendet einen separaten Container mit PHP CLI – dies isoliert die Testausführung von der Hauptanwendung. - Die Datenbank wird mit einem sauberen Schema gestartet. Für jeden Testlauf können wir sie neu erstellen.
- Der MySQL-Port wird auf
3307weitergeleitet, um die lokale Datenbank des Entwicklers nicht zu beeinträchtigen.
1.2. Dockerfile für die PHP-Anwendung
Erstellen Sie ein Dockerfile für den Hauptdienst php:
FROM php:8.2-fpm
RUN docker-php-ext-install pdo_mysql mysqli
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY . .
RUN composer install --no-interaction --prefer-distDieses Image wird sowohl für die Entwicklung als auch für Tests verwendet. Es ist wichtig, die Erweiterung pdo_mysql zu installieren – ohne sie schlagen Tests, die mit der Datenbank arbeiten, fehl.
2. Schreiben von Integrationstests mit PHPUnit
2.1. Grundlegende PHPUnit-Konfiguration
Stellen Sie sicher, dass PHPUnit installiert ist (über Composer). Die Datei phpunit.xml sollte auf die Testdatenbank verweisen:
<?xml version="1.0" encoding="UTF-8"?><phpunit bootstrap="vendor/autoload.php"> <php> <env name="DATABASE_URL" value="mysql://test_user:test_pass@db:3306/test_db" /> <env name="APP_ENV" value="test" /> </php> <testsuites> <testsuite name="Integration"> <directory>tests/Integration</directory> </testsuite> </testsuites></phpunit>2.2. Beispiel eines Integrationstests: Arbeiten mit der Datenbank
Nehmen wir an, wir haben ein Benutzer-Repository. Schreiben wir einen Test, der das Speichern und Suchen überprüft:
<?php
namespace App\\Tests\\Integration;
use App\\Entity\\User;use App\\Repository\\UserRepository;use Doctrine\\ORM\\EntityManagerInterface;use Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase;
class UserRepos