<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://julien-becheny.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://julien-becheny.github.io/" rel="alternate" type="text/html" hreflang="fr" /><updated>2026-09-25T09:33:34+00:00</updated><id>https://julien-becheny.github.io/feed.xml</id><title type="html">Julien Becheny</title><subtitle>Ingénieur QA Automation. Notes sur l&apos;automatisation des tests, le mobile natif, la performance et l&apos;outillage qui rend les tests fiables.</subtitle><author><name>Julien Becheny</name></author><entry><title type="html">Un bouton, quatre sélecteurs, un seul test</title><link href="https://julien-becheny.github.io/blog/un-selecteur-par-plateforme/" rel="alternate" type="text/html" title="Un bouton, quatre sélecteurs, un seul test" /><published>2026-09-22T00:00:00+00:00</published><updated>2026-09-22T00:00:00+00:00</updated><id>https://julien-becheny.github.io/blog/un-selecteur-par-plateforme</id><content type="html" xml:base="https://julien-becheny.github.io/blog/un-selecteur-par-plateforme/"><![CDATA[<p>L’application que je teste tourne sur Android, iOS, iPadOS et Windows. Même code
applicatif, même écran, même bouton.</p>

<p>Et quatre façons de le trouver.</p>

<h2 id="pourquoi-quatre">Pourquoi quatre</h2>

<p>L’identifiant est pourtant unique : le développeur l’a posé une fois, dans le
code partagé. Ce qui change, c’est <strong>l’attribut sous lequel chaque système
d’exploitation l’expose</strong> à l’automatisation.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Android    //*[@resource-id='...']
iOS        //*[@name='...']
Windows    //*[@AutomationId='...']
iPadOS     parfois encore autre chose
</code></pre></div></div>

<p>Le dernier cas mérite qu’on s’y arrête. iPadOS partage l’essentiel de son
comportement avec iOS, mais pas toujours : une disposition en plusieurs colonnes,
un composant qui devient une barre latérale, un élément présent sur l’un et
absent sur l’autre. Traiter iPad comme un iOS suffit dans la majorité des cas, et
échoue dans quelques-uns. C’est exactement le genre d’exception qui empoisonne
une architecture si on ne lui prévoit pas de place.</p>

<h2 id="les-deux-réflexes-et-ce-quils-coûtent">Les deux réflexes, et ce qu’ils coûtent</h2>

<p><strong>Dupliquer la suite par plateforme.</strong> Chaque scénario existe en quatre
exemplaires. Une évolution fonctionnelle se répercute quatre fois, et le jour où
l’une des copies prend du retard, plus personne ne sait laquelle fait foi. La
maintenance est multipliée par quatre, mais surtout, la confiance est divisée.</p>

<p><strong>Semer des conditions dans les tests.</strong> Le scénario métier se retrouve noyé sous
la plomberie. Un test censé décrire un parcours d’achat parle soudain de
<code class="language-plaintext highlighter-rouge">resource-id</code> et de <code class="language-plaintext highlighter-rouge">AutomationId</code>. Il devient illisible pour la seule personne
qui devrait pouvoir le relire : celle qui connaît le métier, pas l’outil.</p>

<p>Les deux approches ont le même défaut de fond : elles laissent une question
d’infrastructure remonter jusqu’au niveau où l’on décrit le comportement attendu.</p>

<h2 id="le--if--ne-disparaît-pas-il-déménage">Le « if » ne disparaît pas, il déménage</h2>

<p>C’est tout le principe, et il tient en une phrase.</p>

<p>La condition est irréductible : quatre plateformes exposent quatre attributs, il
faudra bien choisir à un moment. Ce qui se décide, c’est <strong>où</strong> ce choix est
écrit.</p>

<p>Une seule couche le porte. Les tests n’en savent rien. Les éléments sont déclarés
au même endroit, avec deux cas de figure :</p>

<ul>
  <li><strong>identifiant commun aux plateformes</strong> : une ligne, et le sélecteur de chaque
système est dérivé automatiquement ;</li>
  <li><strong>comportement divergent</strong> : on surcharge uniquement la plateforme concernée.</li>
</ul>

<p>Le second point est ce qui rend le premier tenable. Sans lui, la moindre
exception ferait sauter tout l’édifice et ramènerait les conditions dans les
tests.</p>

<h2 id="ce-que-ça-change-concrètement">Ce que ça change, concrètement</h2>

<p>Une montée de version du système qui casse un sélecteur iOS, c’est <strong>une ligne à
corriger</strong>. Pas une chasse à travers toute la suite, pas un inventaire des
endroits où cet élément est mentionné.</p>

<p>C’est la différence entre un correctif de deux minutes et une demi-journée de
recherche, répétée à chaque mise à jour majeure. Sur un cycle de plusieurs
années, c’est cette ligne-là qui décide si la suite de tests survit ou si elle
est abandonnée.</p>

<h2 id="les-règles-de-repli">Les règles de repli</h2>

<p>Trois règles, dans cet ordre :</p>

<ol>
  <li><strong>iPadOS retombe sur iOS</strong> quand aucun sélecteur spécifique n’est déclaré.</li>
  <li><strong>Toute plateforme retombe sur un <code class="language-plaintext highlighter-rouge">default</code></strong> commun.</li>
  <li><strong>Rien de trouvé lève une erreur explicite</strong>, plutôt que de rendre une valeur
vide qui échouerait vingt lignes plus loin.</li>
</ol>

<p>Le troisième point est le plus important, et c’est celui qu’on oublie en écrivant
ce genre de couche. Un sélecteur introuvable qui renvoie une chaîne vide produit
un échec à retardement, dans un message qui ne parle ni de plateforme ni de
déclaration manquante. Mieux vaut échouer tout de suite, en nommant la cause.</p>

<h2 id="ne-pas-déclarer-la-plateforme-à-la-main">Ne pas déclarer la plateforme à la main</h2>

<p>Un dernier détail fait la différence à l’usage : la couche peut lire la
plateforme <strong>directement depuis la session d’automatisation en cours</strong>, au lieu
de la recevoir en paramètre.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">use_appium</span><span class="p">(</span><span class="n">driver</span><span class="p">)</span>      <span class="c1"># la session connaît déjà sa plateforme
</span><span class="n">LOGIN</span><span class="p">.</span><span class="n">resolve</span><span class="p">()</span>         <span class="c1"># le bon sélecteur, sans rien déclarer
</span></code></pre></div></div>

<p>L’intérêt n’est pas d’économiser une ligne. C’est qu’une déclaration manuelle est
une information dupliquée, donc une information qui finira par mentir : on lance
sur iPad avec un paramètre resté sur <code class="language-plaintext highlighter-rouge">ios</code>, et le test échoue en désignant un
élément, jamais la configuration.</p>

<h2 id="extrait-nettoyé-publié">Extrait, nettoyé, publié</h2>

<p>Ce besoin n’a rien de spécifique à mon projet. Toute équipe qui teste la même
application sur plusieurs systèmes rencontre exactement le même mur.</p>

<p>Je l’ai donc sorti de mon dépôt :</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install </span>crosslocator
</code></pre></div></div>

<p>Zéro dépendance d’exécution, typé, sous licence MIT. Il fournit des mots-clés
Robot Framework, et des exemples exécutables sans appareil connecté, pour qu’on
puisse le juger avant de l’installer quelque part.</p>

<p>L’adoption se fait <strong>écran par écran</strong> : rien n’oblige à convertir une suite
entière. Un seul écran migré suffit à voir ce que ça donne.</p>

<h2 id="ce-quil-ne-fait-pas">Ce qu’il ne fait pas</h2>

<p>Un mot là-dessus, parce que c’est ce qui manque à la plupart des annonces
d’outils.</p>

<p>Il <strong>n’encapsule pas le driver</strong>. Il ne fait que router des chaînes de
sélecteurs, et vous les passez à votre bibliothèque habituelle comme avant. C’est
délibéré : une couche qui s’interpose entre le test et le driver devient une
dépendance dont on ne sort plus, et elle casse à chaque montée de version de ce
qu’elle enveloppe.</p>

<p>Il ne corrige pas non plus un mauvais ancrage. Si votre identifiant est régénéré
à chaque compilation, il sera tout aussi instable une fois déclaré proprement.
Ranger le problème ne le résout pas : c’est une autre discussion, et elle vient
avant celle-ci.</p>

<hr />

<p>Le code, la documentation et les exemples :
<a href="https://github.com/julien-becheny/crosslocator">github.com/julien-becheny/crosslocator</a></p>]]></content><author><name>Julien Becheny</name></author><category term="appium" /><category term="mobile" /><category term="robot framework" /><category term="page object" /><category term="python" /><summary type="html"><![CDATA[Le même bouton se trouve de quatre façons différentes selon la plateforme. Plutôt que dupliquer la suite ou semer des conditions dans les tests, le choix peut déménager dans une seule couche.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://julien-becheny.github.io/assets/img/crosslocator.png" /><media:content medium="image" url="https://julien-becheny.github.io/assets/img/crosslocator.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">70 % du temps de mes tests ne testait rien</title><link href="https://julien-becheny.github.io/blog/injecter-les-donnees-de-test-par-api/" rel="alternate" type="text/html" title="70 % du temps de mes tests ne testait rien" /><published>2026-09-21T00:00:00+00:00</published><updated>2026-09-21T00:00:00+00:00</updated><id>https://julien-becheny.github.io/blog/injecter-les-donnees-de-test-par-api</id><content type="html" xml:base="https://julien-becheny.github.io/blog/injecter-les-donnees-de-test-par-api/"><![CDATA[<p>Les tests automatisés sur application native, c’est lent. Et on veut valider les
livraisons vite.</p>

<p>Alors quand une suite atteint quelques centaines de tests, un objectif s’installe
en permanence : réduire le temps d’exécution. On commence par les suspects
habituels. Paralléliser. Supprimer les attentes fixes. Découper par tags.</p>

<p>J’ai fait tout ça. Puis j’ai mesuré où partait réellement le temps, et la réponse
n’était dans aucune de ces trois cases.</p>

<p><strong>Sept dixièmes du temps d’exécution étaient consommés par la préparation des
données, clic après clic dans l’interface. La vérification, celle pour laquelle
le test existe, tenait dans les trois dixièmes restants.</strong></p>

<h2 id="mesurer-avant-de-décider">Mesurer avant de décider</h2>

<p>Ce chiffre n’était pas une impression. C’est le point important, et c’est
d’ailleurs le seul travail qui n’est pas optionnel dans toute cette histoire.</p>

<p>Un test qui crée un dossier, saisit une fiche, valide un formulaire puis vérifie
qu’un montant s’affiche correctement passe l’essentiel de son temps dans les
trois premières étapes. Aucune d’elles n’est le sujet du test. Elles sont la
condition pour que le sujet existe.</p>

<p>Tant qu’on ne sépare pas ces deux natures dans la mesure, on optimise à l’aveugle.
On gagne trois secondes sur une attente pendant que quarante secondes partent dans
une saisie de formulaire qui ne fait pas l’objet du test.</p>

<h2 id="le-setup-par-linterface-coûte-deux-fois">Le setup par l’interface coûte deux fois</h2>

<p>Le coût évident, c’est le temps. Il y en a un second, moins visible et plus cher.</p>

<p>Chaque écran traversé pour préparer une donnée est une occasion de casser. Un
libellé qui change, un champ qui se décale, une popup de mise à jour qui
s’intercale, une lenteur réseau sur un écran intermédiaire. Le test échoue, et il
échoue <strong>dans une étape qui ne l’intéressait pas</strong>.</p>

<p>C’est la pire catégorie d’échec. Le rapport est rouge, mais le produit va bien.
Il faut ouvrir les journaux, comprendre qu’on est tombé à l’étape 4 sur 12, et
constater que rien de ce que le test devait vérifier n’a été atteint. Le temps
perdu à diagnostiquer dépasse souvent le temps qu’on cherchait à économiser.</p>

<p>Plus grave encore : à force, l’équipe apprend que le rouge ne veut rien dire.</p>

<h2 id="le-principe--séparer-la-mise-en-condition-de-la-vérification">Le principe : séparer la mise en condition de la vérification</h2>

<p>Le pattern tient en une phrase : <strong>mise en condition par l’API, vérification par
l’interface</strong>.</p>

<p>Le test ne clique plus pour créer son contexte. Il l’obtient par des appels
directs, en quelques secondes. Puis il ouvre l’application et vérifie uniquement
ce qu’il est censé vérifier.</p>

<p>Ce n’est pas une astuce de contournement. C’est une remise au bon niveau : un test
doit passer son temps sur son sujet. Tout le reste est de l’infrastructure, et
l’infrastructure n’a pas à être jouée par un humain simulé.</p>

<h2 id="quand-ne-pas-le-faire">Quand ne pas le faire</h2>

<p>C’est la partie que les articles sur ce sujet oublient, et c’est elle qui décide
si le pattern tient dans la durée.</p>

<p><strong>Quand le parcours utilisateur est le sujet du test, on reste intégralement sur
l’interface.</strong> Un test qui vérifie qu’on peut créer un dossier doit créer ce
dossier en cliquant. Sinon il ne teste plus rien.</p>

<p>La règle que j’applique est simple à énoncer : si l’étape fait partie de ce que le
test affirme, elle passe par l’interface. Si elle est seulement nécessaire pour
que l’affirmation ait un sens, elle peut passer par l’API.</p>

<p>Conséquence directe : <strong>les deux modes doivent coexister</strong>. Il ne s’agit pas de
migrer une suite de l’un vers l’autre, mais d’avoir les deux disponibles, et de
choisir par test.</p>

<h2 id="ce-que-la-mise-en-œuvre-exige-vraiment">Ce que la mise en œuvre exige vraiment</h2>

<p>Trois contraintes, et elles ne sont pas négociables. Sans elles, on obtient deux
suites de tests au lieu d’une, et la maintenance double au lieu de baisser.</p>

<p><strong>Un seul jeu de données de test.</strong> Les valeurs sont décrites une fois, au même
endroit, indépendamment du chemin par lequel elles arrivent dans l’application.
Le mode d’injection est un détail d’exécution, pas une propriété de la donnée. Si
vous vous retrouvez avec un fichier de données pour l’API et un autre pour
l’interface, ils divergeront avant la fin du mois.</p>

<p><strong>Un seul jeu d’assertions.</strong> Ce qui est vérifié ne change pas selon le mode. Un
test qui n’affirme pas la même chose dans les deux modes n’est plus le même test,
et vous ne pouvez plus comparer leurs résultats.</p>

<p><strong>Un interrupteur, pas une réécriture.</strong> Le basculement se fait par un paramètre
au lancement. Le même fichier de test tourne dans les deux modes. C’est ce qui
permet de vérifier, quand un doute apparaît, que l’écart de comportement vient
bien du produit et non du raccourci.</p>

<h2 id="les-pièges-que-jai-rencontrés">Les pièges que j’ai rencontrés</h2>

<p><strong>L’API et l’interface ne produisent pas exactement le même état.</strong> Un champ
calculé côté client, une valeur par défaut appliquée par le formulaire et pas par
le service, et voilà deux contextes qui se ressemblent sans être identiques. Le
test s’exécute alors sur un état qui n’existerait jamais en production, ou il
échoue pour une raison sans rapport avec ce qu’il vérifie. Le seul remède est de
comparer les deux états réellement obtenus, au lieu de supposer qu’ils coïncident.</p>

<p><strong>Le mappage des données de test existantes vers ce qu’attend le point d’entrée.</strong>
Les jeux de données sont écrits dans le vocabulaire du métier ; l’API attend sa
propre structure, ses propres noms de champs, ses propres formats. Il faut donc
une traduction entre les deux, et cette traduction est du code à maintenir. C’est
le vrai coût d’entrée du pattern, et il est régulièrement sous-estimé : le gain
ne commence qu’une fois cette couche écrite.</p>

<p><strong>Savoir ce que chaque point d’entrée attend vraiment.</strong> Un champ oublié, ou au
contraire un champ envoyé alors qu’il aurait dû rester vide, et le test travaille
sur un contexte faux. Rien ne le signale : l’appel réussit, l’application affiche
quelque chose, le test rend un verdict. C’est le piège le plus coûteux parce
qu’il est silencieux, et un verdict faux vaut moins qu’une erreur franche.</p>

<h2 id="les-résultats">Les résultats</h2>

<p>Sur le périmètre concerné :</p>

<ul>
  <li><strong>Deux à trois fois plus rapide, pour chaque test basculé.</strong> La mise en
condition passe de plusieurs dizaines de secondes à environ deux.</li>
  <li><strong>Nettement moins de tests instables.</strong> Les échecs survenant dans des étapes qui
n’étaient pas le sujet du test ont largement disparu, puisque ces étapes ne sont
plus jouées.</li>
  <li><strong>Le mode intégralement interface reste disponible</strong>, et sert quand il y a un
doute sur un résultat obtenu par injection API.</li>
</ul>

<p>Le gain de temps est celui qu’on met en avant. Ce n’est pourtant pas le plus
important.</p>

<p>Le vrai bénéfice, c’est qu’un test en échec redevient une information. Quand un
test ne traverse plus que ce qu’il vérifie, un rouge signifie quelque chose. Et
un rapport qui signifie quelque chose se lit, au lieu d’être relancé.</p>]]></content><author><name>Julien Becheny</name></author><category term="test automatisé" /><category term="appium" /><category term="robot framework" /><category term="api" /><category term="performance" /><summary type="html"><![CDATA[Sur une suite de tests mobiles, la mise en condition consommait sept dixièmes du temps d'exécution. Comment la déplacer vers l'API, et surtout quand ne pas le faire.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://julien-becheny.github.io/assets/img/injection-api.png" /><media:content medium="image" url="https://julien-becheny.github.io/assets/img/injection-api.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Le test qui échouait n’était jamais celui qui avait le bug</title><link href="https://julien-becheny.github.io/blog/reparer-l-etat-a-l-entree/" rel="alternate" type="text/html" title="Le test qui échouait n’était jamais celui qui avait le bug" /><published>2026-09-21T00:00:00+00:00</published><updated>2026-09-21T00:00:00+00:00</updated><id>https://julien-becheny.github.io/blog/reparer-l-etat-a-l-entree</id><content type="html" xml:base="https://julien-becheny.github.io/blog/reparer-l-etat-a-l-entree/"><![CDATA[<p>Sur une application mobile métier, certains tests modifient des réglages
globaux : une option de facturation, une grille tarifaire, un jour férié. Le
teardown remet tout en place.</p>

<p>Sur le papier.</p>

<h2 id="des-réglages-quon-emprunte-jamais-quon-possède">Des réglages qu’on emprunte, jamais qu’on possède</h2>

<p>Un principe de base veut que chaque test soit maître de ses données. Il crée ce
dont il a besoin, il le nettoie, il n’interfère avec personne. Le principe est
bon, et je l’applique.</p>

<p>Mais il ne couvre pas tout. Certains réglages sont globaux par nature : les tests
ne peuvent que se les partager. <strong>Ils ne les possèdent pas, ils les empruntent.</strong></p>

<p>L’exemple est trivial à décrire. Un paramètre vaut 15 par défaut. Mon test a
besoin qu’il vaille 10. Si la restauration ne passe pas, il reste à 10, et le
test suivant, qui attend 15, tombe.</p>

<h2 id="un-teardown-est-une-promesse-pas-une-garantie">Un teardown est une promesse, pas une garantie</h2>

<p>Il ne s’exécute pas quand l’application plante. Ni quand la session mobile meurt.
Ni quand quelqu’un arrête le run en cours. Dans ces trois cas, le réglage reste
modifié, et la suite continue de tourner dans un monde que plus personne ne
décrit.</p>

<p>Ce n’est pas un défaut d’implémentation qu’on corrigerait en écrivant un
meilleur teardown. C’est structurel : <strong>le teardown vit dans le processus qu’il
est censé rattraper</strong>. Quand ce processus disparaît, il disparaît avec lui. On
peut l’entourer de gestionnaires d’erreurs, de tentatives, de délais de grâce,
on ne change rien au cas qui compte vraiment, celui où il n’y a plus personne
pour exécuter quoi que ce soit.</p>

<h2 id="le-coût-réel-nest-pas-létat-cassé-cest-la-distance">Le coût réel n’est pas l’état cassé, c’est la distance</h2>

<p>Un réglage global modifié ne fait pas échouer le test suivant. Il fait échouer
<strong>certains</strong> tests suivants, parfois des dizaines plus loin, parfois seulement
ceux qui traversent l’écran concerné.</p>

<p>Le rapport affiche alors une grappe d’échecs qui n’ont rien en commun, aucun ne
correspondant à une régression du produit. Le vrai coupable, lui, est passé au
vert : il a fait son travail, il a même parfois détecté le bug qu’on lui
demandait de détecter. Il a juste laissé la pièce en désordre avant de mourir.</p>

<p>Diagnostiquer cette situation demande de remonter la chronologie complète du run,
d’identifier quel test a touché quoi, et de reconstituer l’état à chaque étape.
C’est long, et c’est à refaire à chaque fois. Le symptôme le plus courant, dans
une équipe, c’est la phrase « relance, ça passera ».</p>

<h2 id="une-seconde-ligne-de-défense">Une seconde ligne de défense</h2>

<p>J’ai arrêté de chercher à rendre le teardown infaillible. Pas de l’utiliser : il
reste en place, et c’est lui qui restaure dans la quasi-totalité des exécutions.
Sous Robot Framework, il s’exécute d’ailleurs quel que soit le verdict du test,
comme il doit. Ce qu’il ne sait pas faire, c’est survivre à la mort du processus.</p>

<p>Le changement n’est donc pas un remplacement, c’est un ajout : <strong>une vérification
supplémentaire à l’entrée</strong>. Un test ne suppose plus que la place est propre, il
s’en assure avant de commencer.</p>

<h2 id="écrire-son-intention-avant-dagir">Écrire son intention avant d’agir</h2>

<p>Avant de toucher un réglage sensible, le test inscrit ce qu’il s’apprête à faire
dans un journal d’état, <strong>écrit hors du processus</strong> :</p>

<ul>
  <li>quel paramètre ;</li>
  <li>sa valeur d’origine ;</li>
  <li>la valeur qu’il pose.</li>
</ul>

<p>L’ordre compte. L’écriture précède la modification, jamais l’inverse. Si le
programme meurt entre les deux, le pire scénario est une entrée qui décrit une
modification qui n’a pas eu lieu, et la réparation sera sans effet. L’ordre
inverse produirait le cas dangereux : une modification réelle dont plus rien ne
garde la trace.</p>

<p>Le mot important est <strong>hors du processus</strong>. Une variable, une liste en mémoire,
un attribut de classe : tout cela meurt avec le programme, exactement au moment
où l’information devient nécessaire. Un fichier survit au plantage, à l’arrêt
manuel, et même au redémarrage de la machine.</p>

<h2 id="réparer-à-lentrée-comme-un-utilisateur">Réparer à l’entrée, comme un utilisateur</h2>

<p>Le teardown, quand il s’exécute, restaure la valeur et marque l’entrée soldée.
C’est le cas nominal, et il couvre la grande majorité des exécutions.</p>

<p>Le reste tient dans une seule règle : <strong>chaque setup relit le journal et répare
ce qui traîne</strong>. Si une entrée non soldée est là, c’est qu’un run précédent est
mort en cours de route. Le test remet la valeur d’origine avant de commencer son
propre travail.</p>

<p>Et il la remet <strong>en passant par la vraie interface</strong>, comme le ferait un
utilisateur. C’est un choix, pas une facilité. Écrire directement en base irait
plus vite, mais contournerait tout ce que l’application fait au moment d’un
changement de réglage : les contrôles, les recalculs, les mises en cache, les
effets de bord. On réparerait la valeur sans réparer l’état, et on se retrouverait
avec une incohérence plus difficile à voir que celle qu’on corrigeait.</p>

<p>La conséquence est franche à énoncer :</p>

<blockquote>
  <p>Un test ne fait plus confiance à la sortie du test précédent. Il nettoie à
l’entrée.</p>
</blockquote>

<h2 id="-il-suffirait-disoler-">« Il suffirait d’isoler »</h2>

<p>L’objection vient toujours, et elle est légitime : si chaque exécution avait son
propre compte, le problème disparaîtrait.</p>

<p>La parallélisation est effectivement réglée ainsi, un compte par exécution. Mais
cela ne traite pas le partage à l’intérieur d’une même exécution : dès que deux
tests se succèdent sur le même compte, le second retrouve le paramètre que le
premier n’a pas restauré. L’isolation par compte déplace la frontière, elle ne la
supprime pas.</p>

<p>Il faudrait donc <strong>un compte par test</strong>. C’est jouable quand très peu de tests
touchent à ces paramètres et qu’on vérifie, à chaque ajout, qu’ils ne se marchent
pas dessus. Cette vérification-là est à refaire indéfiniment, et elle repose sur
la vigilance de celui qui écrit le test.</p>

<p>Même dans ce cas, un journal d’état ne coûte rien et ne peut pas nuire.</p>

<h2 id="ce-qui-peut-mal-tourner">Ce qui peut mal tourner</h2>

<p>Peu de choses, et c’est ce qui rend le dispositif intéressant : une fois en place,
il demande très peu d’entretien.</p>

<p>Le seul incident que j’ai eu ne venait pas du mécanisme mais de mon propre code.
L’ajout d’un paramètre critique d’une nature un peu particulière a demandé
d’adapter les mots-clés qui gèrent le journal. Une erreur s’y est glissée, et l’un
des paramètres a cessé d’être mis à jour.</p>

<p>La leçon n’est pas très originale, mais elle mérite d’être dite : un journal
d’état est de l’infrastructure de test, et l’infrastructure de test se régresse
comme le reste. Elle mérite donc ses propres vérifications.</p>

<h2 id="ce-que-je-retiens">Ce que je retiens</h2>

<p>Le teardown reste indispensable. C’est lui qui restaure dès que le test arrive au
bout, c’est-à-dire presque toujours, et rien ne le remplace dans ce rôle. Ce
qu’il ne peut pas faire, par construction, c’est couvrir les cas où le processus
meurt avant lui.</p>

<p>Le journal d’état ne prend pas sa place : il ferme ce trou-là. Et il le ferme
avec une garantie d’une autre nature, qui ne dépend plus du bon déroulement de ce
qui précède, mais seulement de la capacité du test suivant à lire un fichier avant
de commencer.</p>

<p>Un fichier, ça survit.</p>]]></content><author><name>Julien Becheny</name></author><category term="test automatisé" /><category term="appium" /><category term="robustesse" /><category term="robot framework" /><summary type="html"><![CDATA[Un teardown ne s'exécute pas quand le processus meurt. Les tests suivants tombent alors en cascade, très loin du coupable. Ce qu'on peut ajouter pour combler ce trou.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://julien-becheny.github.io/assets/img/teardown-journal-etat.png" /><media:content medium="image" url="https://julien-becheny.github.io/assets/img/teardown-journal-etat.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>