PHP项目集成测试环境怎样搭建

wen PHP项目 4

本文目录导读:

PHP项目集成测试环境怎样搭建

  1. 第一阶段:基础环境隔离(本地开发)
  2. 第二阶段:数据库隔离策略(关键)
  3. 第三阶段:搭建测试框架(工具链)
  4. 第四阶段:CI/CD 持续集成(自动化流水线)
  5. 补充:核心技巧与注意事项
  6. 总结流程图

搭建PHP项目的集成测试环境是一个系统性的工程,需要从环境隔离依赖管理数据库策略测试框架CI/CD五个维度来完善。

以下是详细的搭建指南,分为基础环境数据库策略自动化测试CI/CD四个部分:


第一阶段:基础环境隔离(本地开发)

这一步是为了确保每个人和CI服务器能在一致的环境中运行。

  1. 使用 Docker Compose(强烈推荐) 这是目前最主流的做法,它能保证开发、测试和生产环境的“一致性”。

    • 目录结构

      project/
      ├── docker/
      │   ├── php/
      │   │   └── Dockerfile
      │   ├── nginx/
      │   │   └── default.conf
      │   └── mysql/
      │       └── init.sql  # 测试数据初始化脚本
      ├── docker-compose.yml
      ├── src/          # 你的项目代码
      └── tests/        # 测试代码
    • docker-compose.yml 示例

      version: '3.8'
      services:
        php-fpm:
          build: ./docker/php
          volumes:
            - ./src:/var/www/html
          environment:
            - APP_ENV=testing
            - DB_HOST=mysql
          depends_on:
            - mysql
        nginx:
          image: nginx:alpine
          ports:
            - "8080:80"   # 避免与本地环境冲突
          volumes:
            - ./src:/var/www/html
            - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
          depends_on:
            - php-fpm
        mysql:
          image: mysql:8.0
          environment:
            MYSQL_ROOT_PASSWORD: root
            MYSQL_DATABASE: integration_test
          volumes:
            - ./docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
          ports:
            - "3306:3306"  # 注意:这里做端口映射,如果本地有MySQL,请换一个端口,33061:3306
  2. 环境变量管理(.env) 在测试环境下,我们需要强制加载 .env.testing 文件,切勿把测试配置写在 .env 里,避免误操作生产数据库,可以通过环境变量注入或PHP代码动态加载。

    // 你项目的入口文件或配置文件中(bootstrap.php)
    if (getenv('APP_ENV') === 'testing') {
        $dotenv = Dotenv\Dotenv::createImmutable(__DIR__, '.env.testing');
        $dotenv->load();
    }

第二阶段:数据库隔离策略(关键)

集成测试最危险的是污染开发数据库,因此我们要确保测试数据与业务数据分离。

  1. 方案A:独立的测试数据库(推荐)

    • docker-compose.yml 中,不映射MySQL 3306端口到宿主机(或者在配置文件中通过变量区分),或者直接创建多个数据库。
    • 做法:在 .env.testing 中配置 DB_DATABASE=integration_test确保应用实例使用的是这个数据库
    • 优点:速度快,接近真实环境。
    • 缺点:测试数据可能残留,需要在测试前后清理。
  2. 方案B:事务回滚(最安全,但速度稍慢)

    • 在测试基类中,利用 PHPUnit 或 Codeception 的 DatabaseTransactions Trait。
    • 原理:每个测试用例开始前开启事务,结束时回滚,数据库状态“永远”停留在初始状态。
      // PHPUnit + Laravel 写法示例
      use Illuminate\Foundation\Testing\DatabaseTransactions;

    class UserIntegrationTest extends TestCase { use DatabaseTransactions; // 测试结束后自动回滚

    public function testUserCreation()
    {
        // 创建用户的操作
        $response = $this->post('/api/users', [...]);
        $response->assertStatus(201);
    }
  3. 初始化数据迁移与填充

    • 在测试启动脚本中,必须执行:
      php artisan migrate:fresh --env=testing
      php artisan db:seed --env=testing
      # 或者使用测试专用的 Seed 类
      php artisan db:seed --class=IntegrationTestSeeder --env=testing

第三阶段:搭建测试框架(工具链)

  1. 选择测试工具(根据项目现状选择):

    • PHPUnit:最基础、最底层的单元/集成测试框架(几乎所有框架都内置)。
    • Codeception:更适合做端到端的集成测试,支持模拟浏览器行为(如填表、点击按钮)。
    • Behat:如果你实施BDD(行为驱动开发),则使用它。
  2. 启动脚本配置(phpunit.xml 在项目根目录的 phpunit.xml 中配置测试专用的环境变量,而不是直接手改 .env

    <?xml version="1.0" encoding="UTF-8"?>
    <phpunit bootstrap="vendor/autoload.php">
        <testsuites>
            <testsuite name="Integration">
                <directory>./tests/Integration</directory>
            </testsuite>
        </testsuites>
        <php>
            <!-- 这是关键:强制测试环境使用独立的环境变量 -->
            <env name="APP_ENV" value="testing"/>
            <env name="DB_CONNECTION" value="mysql"/>
            <env name="DB_DATABASE" value="integration_test"/>
            <env name="CACHE_DRIVER" value="array"/>
            <env name="QUEUE_CONNECTION" value="sync"/> <!-- 让队列任务在测试中立即执行 -->
        </php>
    </phpunit>
  3. 模拟外部服务(Mocking 与 Fake) 集成测试的“集成”指的不仅仅是数据库,还包括第三方API(如支付平台、物流平台),如果不希望测试调用真实的支付宝接口,需要用到 Mock。

    • 使用 PHPUnit 的 Mockery

      $paymentGateway = Mockery::mock(PaymentGateway::class);
      $paymentGateway->shouldReceive('charge')->once()->andReturn(['status' => 'success']);
      $service = new OrderService($paymentGateway);
      $result = $service->checkout(100);
    • HTTP 模拟:如果项目使用 Guzzle,可以用 Http::fake()(Laravel自带)或 GuzzleHttp\Handler\MockHandler


第四阶段:CI/CD 持续集成(自动化流水线)

这一步可以在 GitHub Actions 或 GitLab CI 中配置,当代码推送后,自动搭建环境并执行测试。

  1. GitHub Actions 示例(.github/workflows/integration.yml

    name: PHP Integration Tests
    on: [push, pull_request]
    jobs:
      php-integration:
        runs-on: ubuntu-latest
        services:
          mysql:
            image: mysql:8.0
            env:
              MYSQL_ROOT_PASSWORD: secret
              MYSQL_DATABASE: integration_test
            ports:
              - 3306:3306
            options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
        steps:
          - uses: actions/checkout@v4
          - name: Setup PHP
            uses: shivammathur/setup-php@v2
            with:
              php-version: '8.3'
              extensions: pdo, mysqli
          - name: Install Composer Dependencies
            run: composer install --no-interaction --prefer-dist
          - name: Run Database Migrations (在 CI 环境下的测试库操作)
            run: php artisan migrate --env=testing --force
          - name: Run Integration Tests
            run: vendor/bin/phpunit --testsuite Integration --coverage-text
        env:
          DB_HOST: 127.0.0.1
          DB_PORT: 3306
          DB_DATABASE: integration_test
          DB_USERNAME: root
          DB_PASSWORD: secret
  2. 关键点

    • 在 CI 中,我们走的是 phpunit.xml 中的 <env> 设置,或者由 CI 系统提供的 env 注入。
    • 数据库必须使用干净的迁移migrate:fresh)来保证准确性。

补充:核心技巧与注意事项

  1. 必须清理缓存: 配置变更后,需要确保测试代码不使用旧缓存。

    php artisan config:clear --env=testing
  2. 邮件与日志: 在测试环境,将邮件设为 log 驱动,避免真的发送邮件。

    // .env.testing
    MAIL_MAILER=log
    LOG_CHANNEL=single
  3. 文件存储: 测试时生成的文件应放在本地临时目录(storage/app/testing),而不是云存储(S3等)。

总结流程图

开发者 push 代码
      ↓
CI 服务器 (GitHub Actions / Jenkins)
      ↓
启动 Docker MySQL 容器 (挂载空数据卷)
      ↓
执行 Composer Install
      ↓
执行 php artisan migrate --env=testing (重建结构)
      ↓
执行 php artisan db:seed --class=TestDataSeeder (填充基础数据)
      ↓
运行 PHPUnit / Codeception 测试套件
     ↓
测试通过 → 部署到预发布环境 / 失败 → 发送通知

核心原则:隔离性(独立数据库、独立缓存、独立文件存储)和可重复性(每次构建环境一致),如果你能搭建好这套流程,项目的集成测试就能高效、安全地稳定运行。

抱歉,评论功能暂时关闭!