Andrew Hanna

Andrew Hanna

Comment exécuter les tests Apex en parallèle sans échecs aléatoires

Comment exécuter les tests Apex en parallèle sans échecs aléatoires

Pour exécuter les tests Apex en parallèle sans échecs aléatoires, faites en sorte que chaque test crée ses propres données, n'écrive jamais dans des enregistrements extérieurs au test et génère des valeurs uniques pour des champs comme les noms d'utilisateur. Diagnostiquez ensuite chaque test instable restant en relançant sa classe seule : s'il passe seul et échoue en parallèle, c'est un problème d'isolation, pas un bug. Désactiver les tests parallèles pour toute l'org masque le symptôme et ralentit chaque exécution.

Pourquoi les tests Apex échouent-ils seulement en parallèle ?

Par défaut, Salesforce exécute les classes de test asynchrones simultanément : deux tests peuvent donc se disputer la même ressource au même moment. Les échecs se rangent en trois causes :

  • La contention sur les verrous. Une transaction qui attend un enregistrement verrouillé dispose de 10 secondes avant que Salesforce ne renvoie UNABLE_TO_LOCK_ROW, et cette limite n'est pas modifiable, comme l'explique Xappex. Les enregistrements parents sont verrouillés silencieusement lors des mises à jour d'enfants en master-detail, du recalcul des roll-up summaries et du traitement du partage.
  • Les valeurs uniques à l'échelle de Salesforce. Les noms d'utilisateur sont uniques dans tout Salesforce : deux classes qui insèrent [email protected] en même temps échouent avec DUPLICATE_USERNAME, un schéma que Salesforce Central documente.
  • Les données partagées de l'org. Un test en @isTest(SeeAllData=true) lit et modifie de vrais enregistrements que d'autres tests peuvent toucher au même moment.

Aucun de ces problèmes n'apparaît quand une classe s'exécute seule, d'où l'impression d'une suite qui échoue au hasard.

Comment distinguer un échec lié au parallélisme d'un vrai bug ?

  1. Lisez l'erreur. UNABLE_TO_LOCK_ROW, DUPLICATE_USERNAME et les autres erreurs de valeur en double sur des données de test signalent un problème de concurrence.
  2. Relancez la classe seule. L'option --synchronous de la Salesforce CLI exécute de façon synchrone les méthodes de test d'une seule classe Apex, selon la documentation de plugin-apex.
  3. Comparez. Passe seul, échoue en parallèle : problème d'isolation. Échoue dans les deux cas : un vrai défaut. Corrigez-le au lieu de le relancer.
  4. Consignez-le. Notez la classe, l'erreur et la date. Une classe instable deux fois dans le mois passe en tête de la liste des corrections.

Comment rendre les tests Apex sûrs en exécution parallèle ?

  1. Créez toutes les données dans le test. Utilisez @TestSetup ou une data factory et supprimez SeeAllData=true. Les tests qui construisent leurs propres données ne se disputent pas les enregistrements de l'org.
  2. N'écrivez que dans les enregistrements du test. Évitez de modifier les enregistrements de configuration partagés, l'utilisateur courant ou tout ce qu'un recalcul de partage pourrait verrouiller.
  3. Rendez les champs uniques propres à chaque classe. Préfixez les noms d'utilisateur et autres valeurs uniques avec le nom de la classe de test et un nombre aléatoire.
  4. Séparez tests unitaires et tests d'intégration. Une logique testable sans DML ne prend jamais de verrou. Gardez les tests lourds, liés aux données, dans un ensemble plus restreint que vous surveillez de près.
  5. Marquez les classes éprouvées. Winter '18 a introduit @isTest(isParallel=true) pour signaler les classes capables de s'exécuter en parallèle sans les limites de concurrence par défaut, comme le détaille FishOfPrey. Ne l'ajoutez qu'aux classes qui passent de façon répétée en parallèle.

Faut-il simplement activer Disable Parallel Apex Testing ?

Seulement en solution d'urgence. Le paramètre se trouve dans Setup, Apex Test Execution, Options, et exécute les tests asynchrones un par un. Il supprime les échecs liés à la concurrence, mais dans une org riche en classes de test, une exécution complète peut durer bien plus longtemps. Certains outils dépendent du même interrupteur : la documentation de Gearset indique que ses test monitors utilisent la Tooling API et exécutent donc les tests en parallèle, sauf si vous l'activez.

Considérez cette case comme une dette. Activez-la pour débloquer une release, puis corrigez les classes fautives et désactivez-la de nouveau.

Comment exécuter des tests Apex parallèles de façon fiable en CI ?

  • Exécutez en asynchrone par défaut. sf apex run test --test-level RunLocalTests reproduit l'exécution parallèle que verront vos déploiements en production.
  • Produisez des résultats exploitables par machine. Ajoutez --result-format junit --output-dir pour que votre pipeline suive les échecs par classe dans le temps, et --code-coverage pour garder la couverture visible.
  • Classez, puis relancez une seule fois. Ne relancez, en synchrone, que les échecs qui portent une signature de concurrence. Si la relance passe, consignez un test instable ; si elle échoue, faites échouer le build.
  • Surveillez le taux d'instabilité. Un nombre en hausse révèle un problème de conception des tests, pas de plateforme.

Les relances aveugles sont tentantes, mais elles transforment de vrais défauts en builds verts. La même rigueur s'applique quand vous changez d'outil, comme expliqué dans changer d'outil DevOps Salesforce sans casser votre pipeline et dans notre guide pour migrer de Gearset vers Serpent sans interruption.

Les releases en point-and-click rencontrent les mêmes échecs, car les tests s'exécutent toujours au déploiement. Notre checklist de déploiement en un clic indique quoi vérifier d'abord, et vous trouverez d'autres guides pratiques dans SF Guides.

Qui est Tekunda ?

Tekunda est la société de conseil et de produits Salesforce qui développe Serpent, une plateforme DevOps Salesforce avec gestion des sources sur GitHub et pipelines de déploiement automatisés. Si des tests instables bloquent vos releases, comparez les offres sur notre page tarifs.

FAQ

Salesforce exécute-t-il les tests Apex en parallèle par défaut ?

Oui, les exécutions asynchrones lancent les classes simultanément, sauf si Disable Parallel Apex Testing est activé dans Setup.

Quelle est la cause de UNABLE_TO_LOCK_ROW dans les tests Apex ?

Deux transactions veulent le même enregistrement, souvent un parent verrouillé par une mise à jour master-detail, un roll-up summary ou un recalcul du partage. Celle qui attend échoue au bout de 10 secondes.

Faut-il relancer automatiquement les tests Apex instables ?

Une seule fois, en synchrone, et uniquement pour les erreurs de concurrence. Consignez chaque cas et corrigez la classe plutôt que de compter sur les relances.

isParallel=true suffit-il à corriger les tests instables ?

Non. L'annotation indique seulement qu'une classe peut tourner en parallèle. Le test doit toujours créer ses propres données et utiliser des valeurs uniques.

Articles similaires

Curieux de livrer plus vite avant de vous lancer ? Parlons-en

Sans engagement.