L'illusion de la sécurité

Nous y sommes tous passés. Ce moment satisfaisant où vous voyez tous ces coches vertes sur votre tableau de bord CI/CD. C'est comme une tape dans le dos des dieux du code eux-mêmes. Mais voici le hic : ces tests pourraient vous donner un faux sentiment de sécurité.

Pourquoi ? Eh bien, décomposons cela :

  • Couverture de test incomplète
  • Tests instables qui réussissent... parfois
  • Tests qui n'affirment pas réellement ce que vous pensez
  • Différences environnementales entre test et production

Chacun de ces facteurs peut contribuer à ce que j'aime appeler le "Mensonge Vert" - lorsque vos tests réussissent, mais que votre code est toujours aussi stable qu'un château de cartes dans un ouragan.

Le dilemme de la couverture

Parlons de la couverture de test. C'est une métrique qui circule comme une patate chaude dans les équipes de développement. "Nous avons 80% de couverture !" proclameront-ils fièrement. Mais voici une réflexion à méditer : 100% de couverture de test ne signifie pas que 100% du comportement de votre code est testé.

Considérez cette fonction JavaScript apparemment simple :


function divide(a, b) {
  return a / b;
}

Vous pourriez écrire un test comme celui-ci :


test('diviser 4 par 2 égale 2', () => {
  expect(divide(4, 2)).toBe(2);
});

Félicitations ! Vous avez 100% de couverture. Mais qu'en est-il de la division par zéro ? Qu'en est-il de la précision des nombres à virgule flottante ? Qu'en est-il des grands nombres ? Votre test vous ment, vous donnant un faux sentiment de sécurité.

Le fiasco des tests instables

Ah, les tests instables. Le fléau de l'existence de chaque développeur. Ce sont les tests qui réussissent 9 fois sur 10, vous berçant dans un faux sentiment de sécurité, pour échouer spectaculairement quand vous vous y attendez le moins.

Les tests instables sont souvent le résultat de :

  • Conditions de course
  • Logique dépendante du temps
  • Dépendances externes
  • Contraintes de ressources

Voici un exemple classique d'un test potentiellement instable :


test('l'utilisateur est créé', async () => {
  await createUser();
  const users = await getUsers();
  expect(users.length).toBe(1);
});

Ça a l'air innocent, non ? Mais que se passe-t-il si getUsers() est appelé avant que la base de données ait fini de créer l'utilisateur ? Vous avez un test instable qui réussira la plupart du temps, mais échouera juste assez souvent pour vous rendre fou.

L'hypothèse d'assertion

Parfois, le problème n'est pas ce que nous testons, mais comment nous le testons. Considérez ce test Python :


def test_user_registration():
    user = register_user("[email protected]", "password123")
    assert user is not None

Ce test réussira tant que register_user renvoie quelque chose qui n'est pas None. Mais cela signifie-t-il vraiment que l'utilisateur a été enregistré avec succès ? Et si la fonction renvoie toujours un dictionnaire vide en cas d'échec ? Notre test nous donne un feu vert, mais la réalité pourrait être très différente.

L'énigme de l'environnement

Voici un fait amusant : votre environnement de test et votre environnement de production sont aussi similaires qu'une aire de jeux et une zone de guerre. Bien sûr, ils peuvent sembler identiques en surface, mais les dynamiques sont complètement différentes.

Les éléments qui peuvent différer entre test et production :

  • Volume et variété des données
  • Latence et fiabilité du réseau
  • Utilisateurs concurrents et charge
  • Comportements des services externes

Vos tests peuvent réussir haut la main dans un environnement de test immaculé, pour s'effondrer spectaculairement face aux dures réalités de la production.

Alors, que pouvons-nous faire ?

Avant de lever les mains au ciel et de déclarer tous les tests futiles, prenez une grande respiration. Il existe des moyens de combattre les tests mensongers et de construire des pipelines CI/CD plus fiables :

  1. Améliorer la qualité de la couverture de test, pas seulement la quantité : Ne vous contentez pas de viser un pourcentage de couverture élevé. Assurez-vous que vos tests testent réellement des scénarios significatifs.
  2. Implémenter l'ingénierie du chaos : Introduisez intentionnellement des échecs et des cas limites dans vos environnements de test pour découvrir des problèmes cachés.
  3. Utiliser les tests basés sur les propriétés : Au lieu de coder en dur des cas de test, générez une large gamme d'entrées pour détecter des cas limites auxquels vous n'auriez pas pensé.
  4. Surveiller la fiabilité des tests : Suivez les tests instables et priorisez leur correction. Des outils comme Flaky peuvent aider à identifier les tests incohérents.
  5. Simuler des conditions proches de la production : Utilisez des outils comme LocalStack pour créer des environnements de test plus réalistes.

À retenir

Rappelez-vous, un pipeline CI vert n'est pas une garantie de code sans bug. C'est un point de départ, pas la ligne d'arrivée. Abordez toujours vos tests avec une bonne dose de scepticisme et une volonté d'approfondir.

Comme le dit le proverbe, "Faites confiance, mais vérifiez." Dans le monde du CI/CD, nous devrions peut-être modifier cela en "Faites confiance à vos tests, mais vérifiez comme si votre production en dépendait." Parce que, eh bien, c'est le cas.

"Le type de test le plus dangereux est celui qui vous donne une fausse confiance." - Développeur anonyme qui a été brûlé une fois de trop

Alors la prochaine fois que vous voyez cette mer de vert satisfaisante sur votre tableau de bord CI, prenez un moment pour vous demander : "Mes tests me disent-ils la vérité, toute la vérité, et rien que la vérité ?" Votre futur vous (et vos utilisateurs) vous en remercieront.

Réflexion

Avant de partir, voici quelque chose à méditer : Combien de temps passez-vous à écrire des tests par rapport à analyser et améliorer vos tests existants ? Si vous êtes comme la plupart des développeurs, la réponse est probablement "pas assez." Peut-être est-il temps de changer cela ?

Rappelez-vous, dans le monde du développement logiciel, un peu de paranoïa peut faire beaucoup de bien. Bon test, et que vos déploiements en production soient toujours en votre faveur !