# Intégrer PHPUnit dans GitHub Actions avec une matrice de versions PHP et WordPress

> Tester un plugin sur une seule version de PHP ne dit rien de sa compatibilité réelle. Voici comment construire une matrice GitHub Actions qui couvre plusieurs combinaisons PHP et WordPress.

- Auteur : Clément Hadrot
- Publié le : 2022-03-23
- Mis à jour le : 2022-03-23
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/integrer-phpunit-github-actions-matrice/

## L’essentiel

- Une matrice qui croise versions PHP et versions WordPress
- MySQL en service Docker directement dans le workflow
- Un cache Composer qui divise le temps de build

Un plugin distribué sur le répertoire officiel de WordPress, ou vendu à plusieurs clients hébergés différemment, doit fonctionner sur un éventail de configurations bien plus large que le seul poste du développeur qui l'a écrit. PHP 7.4 chez un hébergeur, PHP 8.0 chez un autre, WordPress à jour d'un côté, WordPress en retard de deux versions mineures de l'autre : chaque combinaison peut révéler un comportement différent. GitHub Actions permet de tester toutes ces combinaisons automatiquement, à chaque push, grâce à son système de matrice.

Cet article détaille la construction d'un workflow GitHub Actions complet pour une suite PHPUnit WordPress, avec base de données MySQL en service, cache Composer, et une matrice qui croise plusieurs versions de PHP et de WordPress.

## Structure de base du workflow

Un workflow GitHub Actions se définit dans un fichier YAML sous `.github/workflows/`. La structure de base pour une suite PHPUnit WordPress ressemble à ceci :

```
name: Tests PHPUnit

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  phpunit:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
```

Le service MySQL démarre en parallèle du job, dans un conteneur Docker géré directement par GitHub Actions, avec une vérification de santé qui attend que la base soit réellement prête à accepter des connexions avant de continuer.

## Construire la matrice de versions

La section `strategy.matrix` permet de déclarer plusieurs axes de variation, que GitHub Actions combine automatiquement pour exécuter un job par combinaison :

```
strategy:
      fail-fast: false
      matrix:
        php: [ '7.4', '8.0', '8.1' ]
        wordpress: [ '5.9', '6.0' ]
```

Avec trois versions de PHP et deux versions de WordPress, GitHub Actions exécute automatiquement six jobs en parallèle, chacun avec sa propre combinaison. L'option `fail-fast: false` est importante : sans elle, GitHub Actions annule les jobs restants dès qu'une combinaison échoue, ce qui masque des informations utiles sur les autres combinaisons.

> L'essentiel à retenir : Une matrice qui croise versions PHP et versions WordPress ; MySQL en service Docker directement dans le workflow ; Un cache Composer qui divise le temps de build

## Installer PHP et les dépendances par combinaison

```
steps:
      - uses: actions/checkout@v3

      - name: Installer PHP ${{ matrix.php }}
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          extensions: mysqli
          coverage: none

      - name: Cache des dépendances Composer
        uses: actions/cache@v3
        with:
          path: vendor
          key: composer-${{ matrix.php }}-${{ hashFiles('composer.lock') }}

      - name: Installer les dépendances
        run: composer install --prefer-dist --no-progress
```

Le cache Composer, indexé à la fois sur la version de PHP et sur le hash du fichier `composer.lock`, évite de retélécharger les mêmes paquets à chaque exécution tant que les dépendances n'ont pas changé. Sur un projet avec une dizaine de dépendances de développement, ce cache divise souvent par deux ou trois le temps total du job.

## Installer WordPress à la version demandée

Le script `bin/install-wp-tests.sh`, généré par `wp scaffold plugin-tests`, accepte la version de WordPress en dernier paramètre. On l'appelle en réutilisant la variable de matrice :

```
- name: Installer l'environnement de test WordPress
        run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 ${{ matrix.wordpress }}

      - name: Lancer PHPUnit
        run: vendor/bin/phpunit
```

Notez l'utilisation de `127.0.0.1` plutôt que `localhost` pour l'hôte MySQL : dans certains environnements Docker, `localhost` tente une connexion par socket Unix plutôt que par le port exposé, ce qui échoue silencieusement face à un service MySQL démarré en conteneur.

## Lire les résultats efficacement

Avec six combinaisons en parallèle, l'onglet Actions de GitHub affiche un résumé clair : chaque combinaison apparaît comme un job distinct, avec son propre statut. Un tableau récapitulatif aide à interpréter les priorités :

| Situation | Priorité |
| --- | --- |
| Échec sur toutes les combinaisons | Bug réel dans le code, à corriger immédiatement |
| Échec uniquement sur une version PHP ancienne | Vérifier la compatibilité descendante avant de publier |
| Échec uniquement sur une version WordPress récente | Anticiper une fonction dépréciée ou modifiée |
| Échec isolé, non reproductible localement | Suspecter un test instable plutôt qu'un vrai bug |

> Sur nos projets distribués publiquement, nous gardons toujours au moins la version de PHP minimale annoncée dans l'en-tête du plugin dans la matrice. C'est la seule façon de garantir que la compatibilité affichée aux utilisateurs correspond à la réalité testée, et pas seulement à une intention.

## En résumé

Une matrice GitHub Actions transforme une suite PHPUnit qui ne prouve la compatibilité que sur une seule configuration en une vérification systématique de toutes les combinaisons réellement utilisées par vos clients. Le coût, quelques minutes de calcul supplémentaires par push, reste négligeable comparé au temps perdu à diagnostiquer en production un bug de compatibilité qu'un job de matrice aurait détecté en quelques secondes.
