PHP与Docker集成测试:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

PHP与Docker集成测试:从入门到精通



现代PHP开发离不开高质量的测试。如果单元测试检查的是独立的代码片段,那么集成测试则确保系统的所有组件(数据库、Redis、外部API和文件系统)能够协同工作。Docker使这一过程可重现、快速且独立于开发环境。本文将从头讲解如何使用Docker配置PHP应用程序的集成测试。



为什么Docker是集成测试的理想工具?



传统集成测试面临的问题:

  • 环境依赖——每个开发者拥有不同版本的MySQL、PHP、Redis。
  • 数据污染——测试会在真实数据库中留下垃圾数据。
  • 并行运行困难——测试之间相互冲突。


Docker解决了这些问题:

  • 每个测试在具有已知依赖版本的纯净容器中运行。
  • 容器相互隔离,运行后自动删除。
  • Docker Compose可一键启动整个基础设施。


第一步:项目结构与Docker Compose



从一个典型的Symfony PHP应用程序开始。创建用于测试环境的docker-compose.test.yml文件:



version: '3.8'services:  php:    build:      context: .      dockerfile: Dockerfile.test    environment:      DATABASE_URL: "mysql://test:test@mysql:3306/test_db?serverVersion=8.0"      REDIS_URL: "redis://redis:6379"    depends_on:      - mysql      - redis

mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: test_db MYSQL_USER: test MYSQL_PASSWORD: test tmpfs: /var/lib/mysql # 数据存储在内存中——速度更快

redis: image: redis:7-alpine tmpfs: /data


Dockerfile.test文件:



FROM php:8.2-cli

RUN docker-php-ext-install pdo_mysqlRUN pecl install redis && docker-php-ext-enable redis

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /appCOPY . .

RUN composer install --no-interaction --prefer-dist

CMD ["vendor/bin/phpunit", "--configuration", "phpunit.xml.dist"]


注意tmpfs——这是将临时文件系统挂载到内存中。数据库和Redis的运行速度将比磁盘快得多,这对快速测试至关重要。



第二步:为集成测试配置PHPUnit



创建单独的配置文件phpunit.integration.xml.dist:



<?xml version="1.0" encoding="UTF-8"?><phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"         bootstrap="tests/bootstrap.php"         colors="true">    <testsuites>        <testsuite name="Integration">            <directory>tests/Integration</directory>        </testsuite>    </testsuites>    <php>        <env name="APP_ENV" value="test"/>        <env name="KERNEL_CLASS" value="App\\Kernel"/>    </php></phpunit>


用于初始化测试环境的tests/bootstrap.php文件:



<?php

require dirname(__DIR__) . '/vendor/autoload.php';

// 等待MySQL和Redis就绪$maxAttempts = 30;$connected = false;

for ($i = 0; $i < $maxAttempts; $i++) { try { $pdo = new PDO( $_ENV['DATABASE_URL'], null, null, [PDO::ATTR_TIMEOUT => 1] ); $connected = true; break; } catch (PDOException $e) { sleep(1); }}\

博客

书籍推荐