# Tester la génération de documents PDF accessibles pour une collectivité

> Un PDF/UA sans balises de structure n'est accessible que de nom. Comment vérifier automatiquement ce que le générateur produit réellement.

- Auteur : WordPress Développement
- Publié le : 2022-05-02
- Mis à jour le : 2022-05-02
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/tester-pdf-accessibles-collectivite/

## L’essentiel

- Un PDF visuellement correct peut être totalement inaccessible aux lecteurs d'écran
- Les balises de structure PDF/UA se contrôlent par script, pas seulement à l'œil
- Le test doit ouvrir le fichier généré, pas seulement vérifier qu'il existe

« Selon la norme ISO 14289 (PDF/UA), un document doit exposer un arbre de structure logique interprétable par les technologies d'assistance. » Cette exigence, citée presque mot pour mot dans le cahier des charges d'une collectivité pour son extension de génération de comptes rendus de conseil municipal, ne se vérifie pas en ouvrant le PDF dans un lecteur classique : un document parfaitement lisible à l'écran peut être entièrement muet pour un lecteur d'écran.

L'extension générait des PDF à partir d'un contenu WordPress structuré en blocs, via une bibliothèque de génération PDF côté serveur. Le rendu visuel était irréprochable — titres, tableaux, en-têtes bien formatés — mais le fichier produit ne contenait aucune balise de structure exploitable : un lecteur d'écran percevait un unique bloc de texte continu, sans hiérarchie ni distinction entre titre et paragraphe.

## Ce qui doit être vérifié, au-delà du rendu visuel

Un PDF/UA valide expose des balises structurelles internes (`<Document>`, `<H1>`, `<P>`, `<Table>`, `<Figure>` avec texte alternatif), consultables par extraction de l'arbre de structure du fichier plutôt qu'à l'œil.

- Présence d'un arbre de structure logique (`StructTreeRoot`) non vide.
- Chaque tableau de données porte des balises `TH` distinctes des `TD`, avec attribut d'échelle correctement renseigné.
- Chaque image porteuse de sens dispose d'un texte alternatif, jamais une image purement décorative marquée comme informative.
- La langue du document est déclarée explicitement dans les métadonnées.
- L'ordre de lecture logique correspond à l'ordre visuel, sans inversion entre colonnes.

## Automatiser le contrôle avec un script d'extraction

Plutôt qu'un contrôle manuel à chaque changement de gabarit, un script Python s'appuyant sur la bibliothèque `pikepdf` extrait l'arbre de structure et vérifie sa présence minimale, exécuté après chaque génération de PDF de test.

> L'essentiel à retenir : Un PDF visuellement correct peut être totalement inaccessible aux lecteurs d'écran ; Les balises de structure PDF/UA se contrôlent par script, pas seulement à l'œil ; Le test doit ouvrir le fichier généré, pas seulement vérifier qu'il existe

```
import pikepdf

def verifier_structure_pdf(chemin_fichier):
    with pikepdf.open(chemin_fichier) as pdf:
        racine = pdf.Root

        if "/StructTreeRoot" not in racine:
            raise AssertionError("Aucun arbre de structure PDF/UA détecté.")

        if "/Lang" not in pdf.docinfo and "/Lang" not in racine:
            raise AssertionError("Langue du document non déclarée.")

    print("Structure PDF/UA minimale présente.")
```

### Intégrer le contrôle dans une suite de tests PHP

Le script Python est appelé depuis la suite PHPUnit via un appel système, ce qui permet de garder le déclenchement du test dans le même flux que le reste de la suite d'intégration continue.

```
class ExportPdfAccessibleTest extends WP_UnitTestCase
{
    public function test_le_compte_rendu_genere_une_structure_pdf_valide(): void
    {
        $chemin = (new ExportCompteRendu())->generer(self::factory()->post->create());

        exec("python3 verifier_structure_pdf.py " . escapeshellarg($chemin), $sortie, $code);

        $this->assertSame(0, $code, implode("\n", $sortie));
    }
}
```

## Cas limite : les tableaux de délibérations

Le point le plus délicat concernait les tableaux récapitulatifs de votes (pour, contre, abstention), fréquents dans les comptes rendus de conseil. La bibliothèque de génération produisait par défaut des cellules toutes marquées `TD`, sans distinguer les en-têtes de colonne, rendant le tableau incompréhensible pour un lecteur d'écran qui énumère les valeurs sans contexte.

```
public function test_le_tableau_de_votes_marque_ses_en_tetes(): void
{
    $chemin = (new ExportCompteRendu())->generer($compte_rendu_id);
    $balises_th = compter_balises_th_dans_pdf($chemin);

    $this->assertGreaterThan(0, $balises_th, 'Le tableau de votes doit exposer des en-têtes TH distincts.');
}
```

> Un export PDF « accessible » qu'on n'a jamais ouvert avec un lecteur d'écran ou un extracteur de structure n'est accessible que dans la documentation commerciale de l'outil qui l'a généré.

## Pour aller plus loin

Ces contrôles automatisés ne remplacent pas un test manuel ponctuel avec un vrai lecteur d'écran, mais ils permettent de détecter en continu une régression de structure introduite par une mise à jour de la bibliothèque de génération PDF ou par un changement de gabarit, bien avant qu'un usager en subisse les conséquences. La génération du document elle-même, elle, reste hors du périmètre de cet article : seule sa vérification structurelle y est traitée.
