You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2功能测试本地正常,GitLab CI运行套件时单测失败

问题背景

本地运行以下测试命令均正常:

./vendor/bin/codecept run functional EndingEndUserPresenceInStructureCest
./vendor/bin/codecept run functional
./vendor/bin/codecept run

但在GitLab CI环境中,单独运行上述指定测试可通过,运行整个功能测试套件时,仅该测试失败,其余测试均正常。

测试代码

class EndingEndUserPresenceInStructureCest
{
    public function _before(FunctionalTester $I)
    {
    }

    public function endingEndUserPresenceInStructure(FunctionalTester $I)
    {
        $I->haveFixtures(['user' => UtenteFixture::className()]);
        $I->haveFixtures(['anagrafica' => AnagraficaFixture::className()]);
        $user = $I->grabFixture('user', 'user');
        $I->amLoggedInAs($user->id);
        $I->amOnRoute('anagrafica', ['tipologia' => '9']);
        $I->see('test_struttura', 'td');
        $I->see('Nuova Anagrafica', 'a');
        $enduser1 = $I->grabFixture('anagrafica', 'enduser1');
        $enduser2 = $I->grabFixture('anagrafica', 'enduser2');
        $I->see($enduser1->cognome, 'a');
        $I->see($enduser2->cognome, 'a');
        $I->amOnRoute('/passaggio/dimissione', ['anagrafica' => $enduser1->idanagrafica]);
        $I->see('data dimissione');
        $I->fillField('Passaggio[data_uscita]', date('Y-m-d H:i:s'));
        $I->fillField('Passaggio[motivazione]', 'Test motivazione della dimissione');
        $I->fillField('Passaggio[destinazione_uscita]', 'Test destinazione uscita');
        $I->click('Salva');
        $I->see('Anagrafica di ' . $enduser1->cognome, 'h1');
    }
}

Codeception配置

actor: Tester
paths:
    tests: tests
    log: tests/_output
    data: tests/_data
    helpers: tests/_support
bootstrap: _bootstrap.php
settings:
    colors: true
    memory_limit: 1024M
modules:
    config:
        Yii2:
            configFile: 'config/test.php'
            cleanup: false
            transaction: false
        Db:
            dsn: 'mysql:host=app_db;dbname=app_test'
            user: 'root'
            password: 'password'
            populate: true
            cleanup: true
            dump: tests/_data/app_test.sql

GitLab CI配置

app-test:
  stage: app-test
  image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
  services:
    - name: mariadb:10.6
      alias: app_db
  variables:
    MYSQL_DATABASE: app_test
    MYSQL_ROOT_PASSWORD: password
  artifacts:
    when: always
    name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME"
    paths:
      - tests/_output/*
      - runtime/*
    exclude:
      - runtime/cache/
    expire_in: 1 week
  script:
    - composer install
    - cp config/{test_,}db.php
    - cp config/ldap_config{_example,}.php
    - cp config/params{_example,}.php
    - cp config/settings{_example,}.php
    - cp config/yii_env_debug{_example,}.php
    - ./vendor/bin/codecept -vvv run functional

排查思路

  • 检查测试隔离性:当前Yii2模块配置transaction: false,测试不会自动回滚事务。其他测试可能修改了数据库数据,导致该测试运行时数据状态异常。可尝试将transaction改为true,让每个测试在独立事务中运行并自动回滚;或在测试的_before/_after方法中手动重置fixture、清理数据。
  • 确认测试执行顺序:本地与CI的测试执行顺序可能不同,该测试在CI中可能运行在修改了相同表数据的测试之后。可在CI中输出测试执行顺序日志,或强制指定该测试的执行顺序,验证是否还会失败。
  • 验证fixture加载逻辑:确认haveFixtures是否在每次测试时都正确重置数据。若其他测试未正确清理fixture数据,可能导致该测试的fixture被污染。可在_before方法中手动调用fixture的重置方法,确保初始数据干净。
  • 对比数据库初始化状态:检查CI环境中tests/_data/app_test.sql是否正确同步,或在CI运行测试前手动执行数据库初始化命令,确保本地与CI的初始数据库状态一致。
  • 分析详细错误日志:CI中已用-vvv开启详细日志,查看tests/_output中的失败详情(如元素未找到、数据库操作失败等),根据具体错误定位问题。
  • 排查时间相关问题:测试中使用date('Y-m-d H:i:s'),确认CI服务器时区与本地是否一致,时区差异可能导致时间字段验证失败,建议使用固定时间或配置统一时区。

内容的提问来源于stack exchange,提问作者Maxxer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:55:18