Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Continuous Integration: Running Tests Automatically

Continuous Integration: Running Tests Automatically

~7 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026

Every test command shown in chapters 91-94 is only worth as much as it actually gets run. A unit test nobody runs before a merge discovers a regression, at the earliest, once it has already landed on the main branch. A CI pipeline closes exactly that gap: it runs the same commands automatically on every push and every merge request.

Two speeds, two jobs

Chapter 93 already explained the speed difference between unit and integration tests - the same split belongs in the pipeline. A fast unit-tests job runs on every single push, a slower integration-tests job (with its own database as a GitLab CI service) only on merge requests against the main branch - keeping the feedback loop short for everyday commits.

.gitlab-ci.yml
stages:
  - static-analysis
  - test

variables:
  COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.composer-cache"

cache:
  key: composer-cache
  paths:
    - .composer-cache/

phpstan:
  stage: static-analysis
  image: mark0x/php-8.4-fpm:latest
  script:
    - composer install --prefer-dist --no-progress
    - vendor/bin/phpstan analyse app/code/Mironsoft/Loyalty --level=5 --no-progress

phpcs:
  stage: static-analysis
  image: mark0x/php-8.4-fpm:latest
  script:
    - composer install --prefer-dist --no-progress
    - vendor/bin/phpcs --standard=Magento2 app/code/Mironsoft/Loyalty

unit-tests:
  stage: test
  image: mark0x/php-8.4-fpm:latest
  script:
    - composer install --prefer-dist --no-progress
    - vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist \
        --coverage-text --colors=never \
        app/code/Mironsoft/Loyalty/Test/Unit
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"'

integration-tests:
  stage: test
  image: mark0x/php-8.4-fpm:latest
  services:
    - name: mysql:8.0
      alias: db
  variables:
    MYSQL_ROOT_PASSWORD: magento
    MYSQL_DATABASE: magento_integration_tests
  script:
    - composer install --prefer-dist --no-progress
    - cp dev/tests/integration/etc/install-config-mysql.php.dist \
        dev/tests/integration/etc/install-config-mysql.php
    - vendor/bin/phpunit -c dev/tests/integration/phpunit.xml.dist \
        app/code/Mironsoft/Loyalty/Test/Integration
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

Tipp: The services entry on integration-tests spins up its own, isolated MySQL container just for that job - the exact same principle as compose.dev.yaml in this project, just for the CI pipeline instead of the local development environment.

Static analysis before the tests

phpstan and phpcs run as their own stage before test - a module with a PHPStan error at level 5 shouldn't have to run through the far slower test suite first just to fail. Chapter 96 digs into exactly that phpstan job.

Achtung: A red, failing integration-tests job that gets ignored because "the database in CI is always a bit flaky anyway" is more dangerous than having no integration test at all - it creates a false sense of safety while real regressions get lost in the noise. An unstable CI job needs fixing or removing, never silently ignoring.

Chapter 96 wraps up block 11 - and the phpstan job from the pipeline above - with a closer look at PHPStan level 5 in this exact module.