web-dev-qa-db-fra.com

Tests unitaires: assertions différées avec Linq

Est-il correct d'ajouter des assertions différées comme celle-ci

var actualKittens = actualKittens.Select(kitten => {
    Assert.IsСute(kitten);
    return kitten
});

Pourquoi? Je peux donc répéter une seule fois, même avec des déclarations qui attendent une collecte matérialisée, par exemple:

CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

Et cela pourrait aussi être non seulement Select mais une méthode avec un itérateur défini et ayant beaucoup de contrôles et de logique (par exemple un certain comptage et filtrage).

Le germe du doute est la complexité de la lecture et du débogage de ce code en cas d'échec du test.

18
SerG

Est-il correct d'ajouter des assertions différées comme celle-ci [..]

Non, ce n'est pas le cas. Pourquoi? Parce que si, pour une raison quelconque, vous supprimez la deuxième affirmation, le test deviendrait toujours vert et vous penseriez qu'il fonctionne toujours, mais ce n'est pas le cas car la collection ne sera pas énumérée. Si vous avez deux ou plusieurs assertions indépendantes, elles continuerai de faire leur travail même si vous en désactivez un.

Considérez cette combinaison:

Assert.IsTrue(actualKittens.All(x => x.IsCute());
CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

Maintenant, même si vous désactivez ou supprimez l'une des assertions, l'autre ferait toujours son travail. De plus, si vous oubliez pour matérialiser la collection, son exécution peut prendre plus de temps, mais elle fonctionnera toujours. Les tests indépendants sont plus robustes et fiables.

Il y a aussi un second non. Je ne sais pas comment les autres frameworks le gèrent, mais si vous utilisez la plate-forme MS Test, vous ne saurez pas quel test a échoué. Si vous double-cliquez sur le test qui a échoué, le CollectionAssert s'affichera comme ayant échoué, mais en réalité, c'est le Assert imbriqué qui a mal tourné et il sera extrêmement difficile à déboguer. Voici un exemple:

    [TestMethod]
    public void TestMethod()
    {
        var numbers = new[] { 1, 2, 3 }.Select(x =>
        {
            Assert.Fail("Wrong number.");
            return x;
        });

        // This will fail and you won't be sure why.
        CollectionAssert.AreEqual(new[] { 1, 2, 3 }, numbers.ToList()); 

    }

Cela signifie que le premier test est en fait inutile car il n'aide pas à trouver un bug. Vous ne savez pas s'il a échoué parce qu'un numéro n'était pas valide ou parce que les deux collections étaient différentes.


Pourquoi? Je peux donc répéter une seule fois, même avec des déclarations qui attendent une collecte matérialisée

Je me demande pourquoi vous vous en souciez? Ce sont des tests unitaires. Vous n'avez pas besoin d'optimiser chaque élément d'entre eux et généralement les tests ne nécessitent pas des millions d'éléments, donc les performances ne devraient pas être un problème.

Vous devrez maintenir de tels tests, alors pourquoi devriez-vous les rendre plus complexes que nécessaires? Écrivez des assertions simples qui fonctionnent.

37
t3chb0t