Votre test unitaire ment (et vous le savez)
\n\nImaginez : vous avez écrit 50 tests unitaires, tous verts, couverture à 90%. Vous êtes satisfait. Mais une semaine plus tard, la production plante. Il s'avère que votre méthode SortArray() fonctionne parfaitement pour [1, 2, 3] et [3, 1, 2], mais échoue sur [int.MaxValue, -1, 0]. Cela vous dit quelque chose ?
Le problème des tests unitaires classiques est le biais du développeur. Vous écrivez des tests pour les données que vous attendez. Les hackers, les utilisateurs réels et les conditions limites aléatoires suivent d'autres règles.
\n\nC'est là qu'interviennent les tests basés sur les propriétés en C# (ou property-based testing). Au lieu de vérifier « si A, alors B », vous décrivez des propriétés qui doivent toujours être vraies. Et le framework génère lui-même des centaines de données d'entrée aléatoires et vérifie vos assertions.
\n\nDans cet article, nous verrons comment intégrer les tests basés sur les propriétés en C# avec la bibliothèque FsCheck, nous écrirons des exemples concrets et nous observerons comment ils attrapent des bugs que les tests classiques laissent passer.
\n\nQu'est-ce que le test basé sur les propriétés ?
\n\nLe test basé sur les propriétés est une approche où vous formulez des invariants (propriétés) de votre programme. Par exemple :
\n- \n
- « Après le tri, la longueur du tableau ne change pas » \n
- « L'ordre inverse de l'inversion d'une chaîne redonne la chaîne originale » \n
- « La somme de deux nombres positifs est toujours positive » \n
Le framework (par exemple, FsCheck) génère des dizaines et des centaines de données d'entrée aléatoires et vérifie que la propriété est vraie pour toutes. Si un contre-exemple est trouvé, le test échoue et vous obtenez les valeurs spécifiques qui ont cassé le code.
\n\nContrairement aux tests unitaires, vous n'écrivez pas Assert.AreEqual(3, Add(1,2)). Vous écrivez Assert(x + y == y + x) — et vous testez la commutativité pour des milliers de paires de nombres.
Différence avec les tests unitaires classiques
\n\n| Tests unitaires | Tests basés sur les propriétés |
|---|---|
| Vérifient des exemples spécifiques | Vérifient des lois générales |
| Les données sont définies par le développeur | Les données sont générées par le framework |
| Laissent passer les cas limites | Explorent automatiquement les limites |
| Faciles à lire | Nécessitent une pensée abstraite |
La bibliothèque FsCheck : votre outil principal
\n\nDans le monde C#, la norme de facto pour les tests basés sur les propriétés est FsCheck (initialement un port de la bibliothèque Haskell QuickCheck). Elle s'intègre avec xUnit, NUnit et MSTest.
\n\nL'installation est simple :
\ndotnet add package FsCheck\ndotnet add package FsCheck.Xunit // pour l'intégration avec xUnit\n\nFsCheck peut générer des données aléatoires pour les primitives (int, string, float), les listes, les tableaux, les tuples et même les types personnalisés (via des générateurs personnalisés).
Écrire notre premier test basé sur les propriétés en C#
\n\nCommençons par quelque chose de simple : vérifions que l'opération d'addition de nombres entiers est commutative.
\n\nusing FsCheck;\nusing FsCheck.Xunit;\n\npublic class AdditionTests\n{\n [Property]\n public bool Commutative_Addition(int x, int y)\n {\n return x + y == y + x;\n }\n}\n\nExécutez le test. FsCheck générera 100 paires aléatoires d'int (par défaut) et vérifiera la propriété. Si aucun contre-exemple n'est trouvé, le test est vert. Si nous avions fait une erreur (par exemple, en écrivant x - y == y - x), le test aurait échoué avec un exemple spécifique : (5, 3) — car 5 - 3 != 3 - 5.
Analyse du code
\n- \n
- [Property] — attribut qui indique à FsCheck qu'il s'agit d'un test basé sur les propriétés. \n
- La méthode retourne un
bool— si elle retournefalse, le test échoue. \n - Les paramètres
int x, int y— FsCheck substituera automatiquement des valeurs aléatoires.