NFluent : l’outil indispensable pour vos tests unitaires
Qu’est-ce que NFluent
C’est une libraire d’Assertion que vous pouvez utiliser avec les principaux framework de tests unitaires (xUnit, NUnit, MsTest,…) et dont le but est de vous faciliter l’écriture et le debug de vos tests unitaires.
Pourquoi l’utiliser
By design, le développeur a peur des tests unitaires, même quand il est convaincu du bien-fondé de la chose et qu’il est à l’aise avec l’écriture de code testable…il reste toujours une petite appréhension.
Personnellement, ma phobie sur ce sujet c’est quand je tombe sur des trucs comme ça :
[TestMethod]
public void TestMethod1()
{ var o = new Foo(); var a = o.Add(1, 2); Assert.AreEqual(a, 4);
}

Je n’ai même pas commencé à débugger que ma tête me fait mal pour les raisons suivantes :
· Le nom de la méthode de test : TestMethod1. Alors oui, j’abuse un peu…dans la vraie vie on rencontre plutôt : TestTraitementOK1, TestTraitementOK2, TestTraitementOKWithParams ce qui fait beaucoup avancer le problème.
· Pas de message custom et je sais juste que j’attends une valeur qui est 3 et que mon traitement renvoi 4. A ce stade, on est obligé de rentrer dans la méthode de test pour savoir ce qui est testé (le SUT) et le cas de test.
· A la lecture du test, on se rend compte que l’Assert est inversé : la valeur attendue est inversé avec la valeur calculé. C’est beaucoup plus sournois et grave que ce que l’on pense car cette erreur est très courante et nous rend méfiant envers le message d’erreur du test.
NFluent (malheureusement) ne va pas faire sortir un coup de poing pour frapper le développeur qui nome mal ses méthodes mais il va vous aider pour les autres points…et aussi pour plein d’autres.
Une syntaxe « naturelle» qui lève toute ambigüité :
Si on reprend l’exemple précédent et qu’on le transcrit en NFluent on a :
Check.That<int>(a).IsEqualTo(4);
Ce qui nous donne en langage humain : « vérifie que mon entier ‘a’ est égal à 4 ». De plus, plus aucune ambiguité entre la valeur testé et celle attendue.
Quelques autres exemples que vous comprendrez sans explications (Je ne mets volontairement pas le reste du test pour vous prouver qu’avec uniquement le « Check » vous comprenez ce que fait votre test en mode « BRAIN OFF ») :
Check.That<User>(u).IsInstanceOf<User>();
Check.That(integers).IsOnlyMadeOf(3, 2, 1).And.HasSize(4);
Check.That(integer).IsPositive().And.Not.IsGreaterThan(100);
Check.That(() => { throw new Exception("test"); }).Throws<Exception>().WithMessage("testX");
Vous comprendrez aussi la différence entre :
Check.That<User>(u).IsEqualTo<User>(v); (on compare les references)
Et
Check.That<User>(u).HasFieldsWithSameValues(v); (on compare les propriétés)
Un message d’erreur clair sans effort
C’est la première chose qui m’a frappé et juste pour ça, ça vaut le coup de l’utiliser, et là pareil : je ne vous mets que les messages d’erreurs et vous verrez que les infos remontés sont riches :
The checked enumerable has 3 elements instead of 4.
The checked enumerable: [1, 2, 3]
The checked value is greater than the threshold.
The checked value: [5]
The expected value: less than [4]
The checked enumerable has 3 elements instead of 4.
The checked enumerable: [1, 2, 3]
The checked enumerable does not contain exactly the expected value(s).
The checked enumerable: ["toto", "titi", "tata"] (3 items)
The expected value(s): ["toti", "titi", "tata"] (3 items)
Des Features sympas:
Sur les types :
Check.That<User>(u).IsEqualTo<User>(v); (on compare les références)
Check.That<User>(u).HasFieldsWithSameValues(v); (on compare les propriétés)
Sur les collections :
var integers = new int[] { 1, 2, 3 };
Check.That(integers).IsOnlyMadeOf(3, 2, 1).And.HasSize(4);
list.Add(new User() { Name = "toto", Id = 1 });
list.Add(new User() { Name = "titi", Id = 1 });
list.Add(new User() { Name = "tata", Id = 1 });
Check.That(list.Properties("Name")).ContainsExactly("toto", "titi", "tata");
Simple à étendre…mais on verra cela dans un prochain billet.
Le seul truc que j’ai à lui reprocher est qu’il s’arrête à la première erreur et n’exécute pas toutes les validations pour renvoyer toutes les faillures :
var maboite = "Cellenza est une boite trop cool";
Check.That(maboite).Contains("AAAA").And.StartsWith("X").And.Contains("CSC");
J’aurais aimé avoir les 3 erreurs plutôt qu’uniquement la première :
The checked string does not contains the expected value(s): "AAAA"
The checked string: ["Cellenza est une boite trop cool"]
The expected substring(s): ["AAAA"]
Vous pourrez trouver beaucoup plus d’infos ici et il est disponible via Nuget…que demande le peuple !
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :