Travailler sur un site international demande de multiplier les tests.

D'abord, si l'interface change, il est parfois intéressant de la tester dans chaque langue. Dans mon cas, ce n'est pas fait. Le principal risque des "langues" est l'affichage des textes (du point de vue design), ce qui ne peut pas être testé de façon automatique. Pour cela, une équipe multilangue qui vérifie les modifications et leurs impacts est plus réaliste.

L'autre aspect important, c'est l'accès au site en fonction de la langue. Si vous avez une stratégie de redirection en fonction de la langue, il faut pouvoir le tester. J'ai l'impression que cela m'a pris du temps, alors qu'au final, c'est tout simple. Mais j'ai exploré beaucoup de pistes sur le sujet.

Le test

class TestProductionFrench < Test::Unit::TestCase
  def setup
    profile = Selenium::WebDriver::Firefox::Profile.new
    profile['intl.accept_languages'] = "it"
    @browser = Watir::Browser.new :firefox, :profile => profile
  end
  def teardown
    @browser.close
  end
  def test_redirection_it
    @browser.goto("http://www.google.com")
    assert_equal("http://www.google.it", @browser.url)
  end
  def test_redirection_fr
    @browser.goto("http://www.google.fr")
    assert_equal("http://www.google.it", @browser.url)
  end
end

L'explication

Pour ce test, je n'ai pas utilisé cucumber, ou autre, mais juste la librairie unitest de ruby, et watir.

  • Ligne 3 à 7 : le setup, joué avant chaque test. On crée un nouveau profil pour Firefox, contenant l'attribut de langue voulu. Puis on charge Firefox.
  • Ligne 9 à 11 : le teardown, qui ferme le navigateur après chaque test.
  • Ligne 13 à 16 : premier test : on charge google.com, et on vérifie ensuite qu'on a bien été redirigé vers google.it (puisque le navigateur signale une préférence pour cette langue)
  • Ligne 18 à 21 : second test, depuis google.fr

Pourquoi j'ai perdu du temps

J'ai perdu du temps à faire fonctionner cela, pour la simple et bonne raison que cela ne marchait pas, et que mes tests testaient donc "mal". La tête dans le guidon, je n'ai pas testé que le fonctionnement du changement de langue soit juste. Je cherchais à corriger le problème là où il n'était pas.

Quelques rappels :

  • Changer la langue préférée pour l'affichage des pages de Firefox ne change pas la langue du navigateur.undefinedundefined
  • Il est facile d'afficher une page qui vous donne la langue préférée de votre navigateur. Voici un exemple de code en PHP :
<?php
    $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
    echo $lang;

Comme je l'ai déjà dit, je développe des tests sous cucumber / watir pour un gros projet. J'ai quelques centaines de scénarios, des milliers d'étapes, le tout regroupé par fonctionnalité. Cela nous permet de voir rapidement si on peut mettre en prod ou non : si une fonctionnalité est testée "instable", il faut lire le rapport détaillé. Deux anecdotes récentes à ce sujet.

Le bug est détecté

L'un des tests fonctionnels crée il y a une semaine pour détecter un bug existant permettait d'éviter la non régression sur ce point. Ce matin, je peste à voix haute en parlant à un collègue, et un autre me dit "mais je l'ai corrigé vendredi". Après test manuel, je confirme, le bug n'est plus présent. Pourtant, le test ne fonctionne pas.

Commence alors une rapide enquête pour comprendre.

Le bug : si un utilisateur remplit un champ particulier, tout semble marcher quand il sauve. Pourtant, si on rafraichit la page, on voit que cela ne marche pas.

Le test a été mis en place au moment du bug, et une partie du test n'avait donc jamais été vérifiée avant la mise en service du test.

La correction a consisté à attendre que l'élément testé soit bien affiché avant de le tester.

J'ai cru voir un petit bug

Plus tôt cette semaine, un collègue me signale qu'il faudrait ajouter un test sur une fonctionnalité particulière. On en discute, mais plus le temps passe, plus je suis sur que nous avons ajouté un test en ce sens récemment.

Après vérification, nous avons bien un test, mais il ne voit pas le bug. Il me laisse un peu de temps pour corriger le test avant de publier sa correction, cela a facilité le travail.

Durant le test, nous vérifions plusieurs éléments, en fonction des options passées.

Nous avons donc une suite de vérifications, en ruby+watir

find = find and (@browser.div.img).exists?
if data['align'] == 'right'
  find = find and (@browser.div.img(:class => 'media-right')).exists?
else
  find = find and (@browser.div.img(:class => 'media-left')).exists?
end

Pour traduire : On vérifie qu'une image est présente, puis si l'option alignement est "droite", je vérifie que l'image est aligné à droite. Sinon, je vérifie à gauche.

Le problème ? Ce test ne teste rien. Tout simplement parce que le parenthésage est mauvais.

En ruby, le and est prioritaire sur le .exists. Je teste donc l'existence d'un booléen au lieu de tester deux booléens.

Le code corrigé ajoute juste des parenthèses pour changer la priorité.

find = find && ((@browser.div.img).exists?)
if data['align'] == 'right'
  find = find && ((@browser.div.img(:class => 'media-right')).exists?)
else
  find = find && ((@browser.div.img(:class => 'media-left')).exists?)
end

Conclusion

Ce que je retiens de ces événements récents ?

  • La communication dans l'équipe est très importante.
  • Tester qu'un test détecte une panne est complexe.
  • Il n'y a pas de règle sur le bon moment pour créer un test : que ce soit pendant une panne ou en dehors, seul un contrôle régulier permet de s'assurer que le test teste.

Lorsqu'un utilisateur lambda signale un bug, il a tendance à penser qu'il est évident, et qu'il n'a pas besoin de donner des informations. On se retrouve alors à devoir analyser des mails ne contenant peu ou pas d'informations, à leur demander des détails, ou à tester plusieurs cas possibles, en espérent "tomber dessus par hasard".

Dans tous les cas, il y a beaucoup de temps "perdu" pour trouver un bug, qui parfois n'est pas lié à votre site web, mais à tout autre chose : mauvaise manipulation, antivirus, etc.

Lorsqu'on emmène sa voiture chez le garagiste, on lui donne souvent plein d'informations inutiles. Je me souviens d'une fois, où je suis arrivé pour lui dire : "je sais pas ce qu'elle a : elle vibre quand je roule, les vibrations augmentent avec la vitesse. Et j'ai du mal à passer les vitesses, comme si ce n'était plus aligné."

La garagiste a dit "je pense que je sais", a été démarré la voiture sur le parking, puis a éteint et a répondu : "Supports moteurs HS : il va falloir les changer". A peu de chose près, je pensais à Bourvil.

(Pour la petite histoire, 2 supports moteurs sur 3 cassés, à la fin d'un voyage de 800km.)

Mais alors, quelles informations donner lors du signalement d'un bug ? toutes celles qui peuvent être utiles :

  • Navigateur (et version : Firefox 3.5 et Firefox 14 se ressemblent, mais ne sont pas identique, loin de là)
  • Système d'exploitation (non, Safari pour windows et pour mac ne se comportent pas de la même façon)
  • Antivirus (pas utile à chaque fois, mais c'est quand il manque qu'il est utile)
  • Messages d'erreur : tous, en entier.
  • Procédure pour reproduire le bug : où cliquez-vous, dans quel ordre...

Parfois, un bug se joue à un détail : vous cliquez sur le bouton, ou alors vous tabulez et validez au clavier ?

Plus vous donnez d'informations précises, plus cela peut être utile à corriger le bug.

Lorsqu'on rencontre des problèmes vraiment étranges sur une fonction particulière, on pense d'abord que cela n'a jamais pu marcher, on ne comprend plus.

Puis on enquête. Et parfois, la cause du problème est une surprise, autant pour nous que pour les personnes touchées. Quelques exemples plus ou moins vieux.

La box qui coupe

Petit retour sur l'article : Les bugs poilus sont-ils solubles dans le temps ?

Au début, il s'agissait d'un simple problème de validation de formulaire AJAX pour une partie des utilisateurs. Ils emblaient tous utiliser une LiveBox. Nous avons éliminé cette piste au bout de plusieurs jours, certains cas ne collant pas.

Mais au final, il semble que ce problème qui nous a occupé pendant plus d'un mois était bien une mise à jour de la LiveBox : la mise à jour suivante a corrigé le problème.

L'antivirus anti web

En général, je ne cite pas, mais cela fait trop de fois où nous rencontrons des problèmes avec Kaspersky.

Deux points sans rapport, tous les deux liés à des classiques du web.

  • Lorsque vous envoyez une photo via certains protocoles, on a un comportement aléatoire :

    • Images non envoyées
    • Images envoyées de façon incomplète.

    Evidemment, il suffit de désactiver Kaspersky pour que cela fonctionne. Selon les navigateurs, nous utilisons le protocole PUT ou le protocole GET. si le get fonctionne, le put pose de nombreux problèmes.

  • Les notifications, très utilisées sur les réseaux sociaux, sont dégradées : le nombre de notifications n'est pas mis à jour après leur lecture, en particulier sur Google+. Là encore, désactiver l'antivirus suffit à régler le problème.

Toutes les notifications ont été lues, et pourtant

La navigation compatible

Lorsqu'on utilise Internet Explorer, il lui arrive de décider d'utiliser le mode compatible sur certains sites. Un utilisateur qui ne fait pas attention pensera utiliser la dernière version du navigateur, mais aura entre les mains un navigateur se comportant comme IE7 ou IE8 dans le meilleur des cas.

Les éditeurs wysiwyg sont particulièrement concernés par ce genre de problème, mais ce ne sont pas les seuls.

Lorsqu'on sait en outre que le mode compatible IE8 est différent d'IE8, on sait qu'on va s'arracher les cheveux pour trouver la cause du problème.

Le plugin défaillant

Les navigateurs sont depuis plusieurs années extensibles : on peut ajouter des fonctionnalités plus ou moins intéressantes. La plupart des développeurs ont installé FireBug par exemple.

Revenons à celle qui me pose problème : "Facebook Disconnect". Cette extension sous chrome permet d'empêcher Facebook de vous traquer. En contre partie, elle bloque des scripts, sans vous demander votre avis. Un exemple ? notre éditeur wysiwym. Ce n'est apparement pas la seule à bloquer l'éditeur, mais la récupération des informations auprès de nos utilisateurs prend beaucoup de temps sur des problèmes aussi pointus.

Conclusion

Les mises à jour automatiques sont une plaie : les utilisateurs ne comprennent pas pourquoi le comportement change sans modification, et pense systématiquement à un problème du produit concerné, pas d'un logiciel tiers.

Certains logiciels s'adjugent des pouvoirs très importants, sans le signaler à leurs utilisateurs, dégradant par la même occasion la navigation sur des sites web qui fonctionnent pourtant parfaitement par ailleurs.

Le juste équilibre dans les tests

Mettre en place des tests fonctionnels automatiques revient à jouer à l'équilibriste entre l'existant (déjà testé et "stable"), les nouvelles fonctionnalités (et leurs effets de bords sur l'existant), et des eléments externes : navigateurs (et mises à jours), plugins, utilisateurs...

Le responsable qualité et l'équipe doivent avoir confiance dans leurs indicateurs, et doivent connaître leurs limites, afin de pouvoir planifier les actions pour éliminer les bugs.

Des tests toujours réussis

J'ai lu récemment que des tests fonctionnels toujours "vert" sont mauvais, qu'ils ne testent rien. (Why 100% Test Pass rates are Bad)

Je ne suis pas d'accord : j'ai la hantise de tests "rouge" : à chaque fois, cela demande d'aller analyser le rapport, vérifier si c'est un faux positif. (Cela arrive régulièrement : même en prévoyant au mieux, il arrive qu'une action dépasse le temps prévue pour s'exécuter, etc.)

Les tests doivent être toujours vert

Si votre écran de contrôle affiche toujours du rouge, vous finirez pas ne plus lui faire confiance. Le problème, c'est que si vous n'avez pas confiance dans des tests automatisés, c'est que vous perdrez du temps à les refaire à la main. Et que lorsqu'ils passeront au rouge, vous penserez à un faux positif avant même de regarder, et vous pourriez laisser passer un bug.

L'important n'est pas la couleur, mais la couverture

Je préfère avoir une couverture de 50% fiable qu'une plus grande couverture mais instable. Il faut bien comprendre qu'un test vert ne dit pas "il n'y a pas de bug sur ce projet", mais plutôt "aucun bug prévu n'a été trouvé cette fois-ci". La différence semble tenue, mais elle est primordiale.

L'équipe doit savoir si les tests ont des lacunes, afin de redoubler d'effort "manuels" dans cette partie. Il ne faut jamais oublier que les tests automatiques ne testent pas tout le projet, mais seulement ce qu'ils sont sensés tester.

Choix des métriques

Le choix des métriques est primordial : cela influe sur le ressenti de la qualité par l'équipe qui développe le produit. (Test automation metrics - what do you report on?)

Mise à jour des métriques

  • En début de projet, la pertinence du "nombre" de bugs est relative. Quand le projet a déjà été livré dans une version beta au public, ce nombre est déjà plus réaliste.
  • Les tests de charge sont importants tout le temps, mais il ne faut jamais oublier le stade d'avancement du projet. Un test de charge qui semble échouer peut ne pas l'être si on le fait durant une "maintenance programmée" du serveur.

Certains pensent qu'il vaut mieux avoir trop de métriques que pas assez. Mais il faut pondérer ceci par le temps pour les analyser et les comprendre.

Stratégie générale

De la même façon, la remise en cause des stratégies de tests doit être régulière. Il est nécessaire de vérifier régulièrement que les tests testent bien, sont stables, détectent bien les vrais bugs.