# Tester un import de 100 000 fiches sans exploser la mémoire de la CI

> Sur un gros catalogue, un import monolithique dépasse la mémoire allouée au runner de CI. Découper le test en lots révèle des comportements différents.

- Auteur : WordPress Développement
- Publié le : 2023-07-26
- Mis à jour le : 2023-07-26
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/tester-import-100000-fiches-memoire-ci/

## L’essentiel

- Import découpé en lots de 500 fiches testables isolément
- Reprise après échec vérifiée par un test dédié
- Limite mémoire de la CI simulée volontairement en local

256 Mo alloués au runner de CI, 100 000 fiches produit à importer, et un test qui charge tout en mémoire avant de commencer le traitement : l'équation ne pouvait pas tenir. Le premier symptôme a été un `Fatal error: Allowed memory size exhausted`, mais uniquement en CI — jamais en local, où la machine de développement dispose de bien plus de ressources.

Ce genre d'écart entre local et CI est un classique qui mérite d'être testé pour lui-même, pas seulement corrigé une fois constaté. La suite a donc été repensée pour que la contrainte mémoire du runner de CI soit reproduite volontairement en local, plutôt que découverte au hasard d'un push.

## Reproduire la contrainte mémoire du runner en local

Un job dédié fixe explicitement `memory_limit` à 128 Mo dans sa configuration PHP, une valeur volontairement plus basse que la limite réelle du runner, pour détecter les dérives avant qu'elles ne deviennent critiques.

```
php -d memory_limit=128M vendor/bin/phpunit --testsuite import
```

Sous cette contrainte, l'ancien import échouait systématiquement dès 40 000 fiches traitées. Le générateur de fixtures produit un fichier CSV synthétique de 100 000 lignes, avec des champs réalistes générés à partir d'un jeu de données de test, jamais de données de production copiées.

## Découper l'import en lots testables isolément

> L'essentiel à retenir : Import découpé en lots de 500 fiches testables isolément ; Reprise après échec vérifiée par un test dédié ; Limite mémoire de la CI simulée volontairement en local

La correction a consisté à traiter le fichier par lots de 500 fiches, chaque lot étant importé, validé, puis libéré de la mémoire avant de passer au suivant. Le test vérifie que la mémoire consommée reste stable d'un lot à l'autre, pas seulement que l'import se termine.

```
public function test_memoire_stable_entre_lots() {
    $import = new ImportCatalogue( $this->fixture_100k );

    $mesures = array();
    while ( $import->traiter_lot( 500 ) ) {
        $mesures[] = memory_get_usage( true );
    }

    $ecart = max( $mesures ) - min( $mesures );
    $this->assertLessThan( 5 * 1024 * 1024, $ecart );
}
```

Un écart supérieur à cinq mégaoctets entre le lot le plus léger et le plus lourd indique une fuite : un tableau qui grossit sans être vidé, ou un objet qui reste référencé après traitement de son lot.

### Vérifier la reprise après un échec en cours de lot

Un import de cette taille finit toujours par être interrompu un jour — coupure réseau, timeout du serveur, redémarrage planifié. Un test simule une interruption au lot 60 sur 200, puis relance l'import et vérifie qu'aucune fiche n'est dupliquée et qu'aucune n'est oubliée.

- Position du dernier lot traité stockée dans une option WordPress
- Reprise exacte au lot suivant, jamais de retour au début
- Contrôle final : 100 000 fiches en base, ni plus ni moins

## Mesurer le temps autant que la mémoire

Le découpage en lots a un effet de bord positif inattendu : chaque lot peut désormais s'exécuter dans une tâche `wp_cron` distincte, ce qui évite également un dépassement du délai maximal d'exécution PHP sur les hébergements mutualisés où l'import est réellement déployé.

> Une limite de ressources qui n'existe qu'en production doit être reproduite en test, sinon elle continuera à être découverte en production.

## Ce que cette suite ne couvre pas

Le format et la validation du CSV source lui-même, avec ses colonnes obligatoires et ses règles de conversion de types, sont couverts par une suite distincte de tests unitaires plus rapides. Cette suite-ci se concentre exclusivement sur le comportement à grande échelle du processus d'import.

## En résumé

Fixer volontairement une limite mémoire basse en local a transformé un bug de production difficile à reproduire en un test reproductible à chaque exécution. Le découpage en lots de 500 fiches, avec reprise après échec vérifiée, a réduit la consommation mémoire de pointe d'un facteur supérieur à quatre par rapport à l'import monolithique initial.
