NOTE D’INGÉNIERIE

Créer un contrôle de régression d’accessibilité iOS sur un Mac cloud

Créer un contrôle de régression d’accessibilité iOS sur un Mac cloud

Un simple changement de libellé, le remplacement d’une icône ou l’ajustement d’une contrainte peut suffire à priver un écran iOS de libellés lisibles, à réduire les zones tactiles ou à tronquer le texte lorsque la taille des caractères augmente. Une vérification manuelle peut difficilement couvrir chaque commit. Une approche plus fiable consiste à figer l’état du simulateur et de l’application sur un Mac cloud, à lancer les audits d’accessibilité avec XCTest, puis à transformer les échecs en contrôles de fusion reproductibles.

Définir d’abord le périmètre du contrôle

Ne commencez pas par parcourir l’ensemble du produit. Sélectionnez d’abord les parcours les plus fréquents, comme l’écran d’accueil après connexion, l’écran principal d’édition et la page de confirmation d’envoi. Chaque cas de test ne doit valider qu’un seul état stable. Les animations, les recommandations aléatoires, l’heure courante et les réponses réseau modifient l’arbre des éléments ; désactivez-les ou injectez des données fixes en mode test.

Pour une première passe, concentrez-vous sur quatre catégories de problèmes :

Contrôle Défaut courant Traitement par le contrôle
Description des éléments Un bouton sous forme d’icône ne possède aucun nom lisible Échec immédiat
Zone tactile Le contrôle est visible, mais difficile à toucher Échec immédiat
Contraste Le premier plan se distingue mal de l’arrière-plan Correction après validation du design
Mise en page du texte Le texte est tronqué ou se chevauche avec une grande taille de caractères Échec immédiat

L’audit automatisé sert à détecter les problèmes qu’une machine peut identifier de manière fiable ; il ne prouve pas que l’ensemble de l’interaction est facile à utiliser. L’ordre de lecture, la clarté des indications et les gestes complexes doivent toujours faire l’objet de vérifications manuelles.

Fournir au test un écran déterministe

Le principal ennemi des tests d’interface est d’obtenir des écrans différents à partir du même point d’entrée. L’application doit reconnaître des arguments de lancement réservés aux tests afin d’effacer les états temporaires, de charger des données fixes et de désactiver les animations inutiles au démarrage. Ces arguments ne doivent modifier que l’environnement de test, sans s’intégrer à la logique métier de production.

let app = XCUIApplication()
app.launchArguments = [
    "-ui-testing",
    "-reset-demo-state",
    "-disable-animations"
]
app.launchEnvironment["TEST_LOCALE"] = "zh-Hans"
app.launch()

Les données de test doivent être préparées dans le processus de l’application, plutôt que de rendre les tests d’interface dépendants d’une API en temps réel. Pour couvrir les états de chargement, d’absence de données, d’erreur et de réussite, créez un argument distinct pour chacun. En cas d’échec, il suffit alors de reproduire la commande, sans attendre qu’une condition distante particulière réapparaisse.

Stabiliser la localisation des éléments

N’utilisez ni le titre d’un bouton ni ses coordonnées pour localiser les contrôles essentiels. Les titres varient avec la langue, tandis que les coordonnées changent selon la fenêtre et la taille du texte. Attribuez aux éléments interactifs un accessibilityIdentifier dont la sémantique reste stable :

checkoutButton.accessibilityIdentifier = "checkout.submit"
cartSummary.accessibilityIdentifier = "checkout.summary"

L’identifiant doit décrire la fonction de l’élément, pas sa position visuelle. Un nom comme footer.orangeButton perd son sens après une refonte, alors que checkout.submit reste valable quelle que soit la mise en page.

Exécuter des audits XCTest ciblés

Lorsque la version du système prend en charge les API concernées, lancez l’audit sur l’écran une fois son état stabilisé. Attendez d’abord l’apparition de l’élément principal, puis démarrez les vérifications afin de ne pas considérer une mise en page transitoire pendant le chargement comme un défaut.

func testCheckoutAccessibility() throws {
    let app = XCUIApplication()
    app.launchArguments = ["-ui-testing", "-reset-demo-state"]
    app.launch()

    let submit = app.buttons["checkout.submit"]
    XCTAssertTrue(submit.waitForExistence(timeout: 10))

    if #available(iOS 17.0, *) {
        try app.performAccessibilityAudit(for: [
            .sufficientElementDescription,
            .hitRegion,
            .contrast,
            .textClipped
        ])
    }
}

Évitez de créer à la hâte une liste globale d’exclusions. Lorsqu’une exclusion temporaire est réellement nécessaire, limitez-la à un écran, à un identifiant d’élément et à un type de problème précis, puis indiquez dans la revue de code les conditions de sa suppression. Sinon, ces exceptions finissent progressivement par devenir des angles morts permanents.

Figer les conditions d’exécution sur le Mac cloud

Commencez par consulter les appareils de simulation et les runtimes actuellement disponibles, puis transmettez une destination explicite depuis le pipeline. Ne supposez pas qu’un appareil portant le même nom existe déjà sur chaque nœud.

xcrun simctl list devices available
xcrun simctl list runtimes

export SIM_DESTINATION='platform=iOS Simulator,name=iPhone 15,OS=17.5'

set -o pipefail
xcodebuild test \
  -project ExampleApp.xcodeproj \
  -scheme ExampleAppUITests \
  -destination "$SIM_DESTINATION" \
  -only-testing:ExampleAppUITests/AccessibilityTests \
  -resultBundlePath "$PWD/TestResults/Accessibility.xcresult"

En pratique, le nom de l’appareil et la version du système doivent être définis comme variables du pipeline et correspondre aux runtimes installés sur le nœud. Avant l’exécution, créez un nouveau simulateur ou, si vous réutilisez un appareil, fermez d’abord l’application et réinitialisez l’état de test. Les tâches parallèles ne doivent pas partager le même simulateur, sous peine de voir la langue, les demandes d’autorisation et les données résiduelles du cas précédent se contaminer mutuellement.

Le modèle de Mac cloud et le choix du nœud ne changent pas les principes de conception des tests. Lorsque vous devez ajouter un environnement d’exécution, vérifiez dans la console les configurations actuellement proposées et consignez la version de Xcode, la version du runtime, la langue et la destination. Vous pourrez ainsi relancer un échec dans des conditions identiques.

Organiser les exécutions par niveaux et traiter les faux positifs courants

Pour chaque demande de fusion, limitez l’exécution aux écrans principaux, à la langue par défaut et à une taille de texte standard, afin de maintenir le délai de retour dans une plage acceptable pour l’équipe. Sur la branche principale, étendez ensuite la couverture à plusieurs langues, aux orientations portrait et paysage, au mode sombre et au texte dynamique. Ne regroupez pas toutes les combinaisons dans une seule méthode de test : en séparant les cas par écran et par état, le nom de l’échec indique déjà son périmètre.

En cas d’échec instable, effectuez les vérifications dans l’ordre suivant :

  1. Vérifiez que l’élément principal a terminé son chargement et qu’il n’est pas seulement présent dans l’arbre des éléments.
  2. Comparez les réglages de langue, de région, de taille du texte, d’orientation et d’apparence.
  3. Vérifiez si les données de test ont été modifiées par l’exécution précédente.
  4. Relancez uniquement la méthode en échec pour déterminer si le problème se reproduit de manière stable.
  5. Conservez le paquet de résultats, la commande exécutée et les paramètres d’environnement, puis déterminez s’il s’agit d’un défaut du produit ou d’une isolation insuffisante du test.

Les règles du contrôle doivent elles aussi être hiérarchisées. Une description manquante, un contrôle impossible à toucher ou un chevauchement de texte justifient de bloquer la fusion. Un problème de contraste encore en attente de validation par l’équipe de design peut d’abord être consigné, mais il doit avoir un responsable et une échéance. L’objectif final n’est pas d’obtenir un rapport toujours entièrement vert, mais de faire en sorte que chaque échec puisse être rattaché à un écran, un état, un élément et des conditions d’environnement précis.

Questions fréquentes

Un audit automatisé remplace-t-il entièrement une vérification humaine ?

Non. Il détecte efficacement les descriptions absentes, les petites zones tactiles ou certains défauts de contraste, mais l’ordre de lecture et la clarté du parcours doivent être évalués manuellement.

Pourquoi le test réussit-il localement mais échoue-t-il sur le Mac cloud ?

Comparez la version du simulateur, la langue, la région, la taille du texte, l’orientation et les données initiales. Ces paramètres doivent être fixés explicitement au lancement.

À quel moment exécuter l’audit d’accessibilité complet ?

Un contrôle rapide des écrans critiques peut accompagner chaque demande de fusion. La matrice complète, avec plusieurs langues et tailles de texte, convient mieux à la branche principale ou à une tâche planifiée.

Nœud physique dédié

Exécutez votre prochaine compilation sur un Mac dans le cloud.

Comparez trois configurations Apple Silicon et choisissez, parmi cinq nœuds internationaux, la région adaptée à votre flux de travail actuel.

Choisir une formule de location