Question

On m'a demandé d'écrire une application de test devant tester une nouvelle procédure stockée sur plusieurs lignes d'une base de données. En gros, je souhaite utiliser l'une des méthodes suivantes:


[Test]
public void TestSelect()
{
    foreach(id in ids)
    {
        DataTable old = Database.call("old_stored_proc",id);
        DataTable new_ = Database.call("new_stored_proc",id);

        Assert.AreEqual(old.Rows[0]["column"],ne_.Rows[0]["column"]);
    }
}

Lorsque j'exécute ce test, si une ligne ne correspond pas à l'autre, tout le test échoue. J'aimerais plutôt compter combien de fois l'assertion a été passée et combien de fois elle a échoué. Est-il possible de faire cela avec NUnit?

Je me rends compte que NUnit est peut-être excessif et que la tâche est simple sans cela… Je voulais juste l'apprendre. ;)

Était-ce utile?

La solution

1) Si les identifiants sont constants et non recherchés au moment de l'exécution du test, créez un support de test unitaire distinct pour chaque identifiant. De cette façon, vous saurez quel identifiant est en train d'échouer. Voir ici pour une description des problèmes liés aux tests pilotés par les données:
http://googletesting.blogspot.com/2008/09/tott -data-driven-driven.html

2) Si vous avez besoin de rechercher dynamiquement les identifiants rendant impossible la création d'un fixture pour chaque identifiant, utilisez la suggestion de akmad avec une modification. Conservez une liste des identifiants où les valeurs ne sont pas égales et ajoutez la liste au message d'erreur. Il sera extrêmement difficile de diagnostiquer un test en échec indiquant uniquement le nombre d'erreurs, car vous ne saurez pas quel identifiant est à l'origine des erreurs.

3) Je ne sais pas à quel point il serait difficile de faire dans NUnit, mais dans PyUnit, lorsque nous devons exécuter des tests sur des données générées dynamiquement, nous créons de manière dynamique des montages de test et les attachons à la classe TestCase faire échouer le test pour chaque donnée qui ne passe pas. Bien que j'imagine que cela serait beaucoup plus difficile sans les capacités dynamiques de Python.

Autres conseils

On dirait que vous affirmez simplement la mauvaise chose. Si vous souhaitez vérifier toutes les valeurs, puis affirmer qu'il n'y a pas d'erreur (ou afficher le nombre d'erreurs), essayez ceci:

[Test]
public void TestSelect()
{
    int errors = 0;
    foreach(id in ids)
    {
        DataTable old = Database.call("old_stored_proc",id);
        DataTable new_ = Database.call("new_stored_proc",id);

        if (old.Rows[0]["column"] != new_.Rows[0]["column"])
        {
            errors++;
        }            
    }

    Assert.AreEqual(0, errors, "There were " + errors + " errors.");
}

Je sais que la question concerne spécifiquement NUnit, mais il est intéressant de noter que Gallio / MbUnit est doté d'une fonctionnalité permettant courir et attraper plusieurs assertions à la fois.

[Test]
public void MultipleTest()
{
    Assert.Multiple(() =>
    {
       Assert.IsTrue(blabla);
       Assert.AreEqual(pik, pok);
       // etc.
    }
}

Le Assert.Multiple intercepte toutes les assertions défaillantes et va les signaler à la fin du test.

Je compte le nombre de lignes qui ne correspondent pas, puis j'écris une assertion qui compare ce nombre à 0 et renvoie le nombre de chaînes non correspondantes dans le message.

vous pouvez également utiliser Assert.Greater pour cela.

P.S. En principe, vous devriez essayer de faire une assertion par test unitaire. C’est l’essentiel.

Eh bien, vous pouvez déclarer un compteur, puis en affirmer la valeur pour déterminer si le test réussit / échoue

Vous pouvez également effectuer la majeure partie du travail dans la configuration du test, puis créer simplement plusieurs tests.

Je ne comprends pas pourquoi vous avez besoin de toutes les affirmations dans le même test.

En fonction de l'objectif que vous avez défini, l'intégralité du test devrait échouer si une ligne ne correspond pas à une autre. Compter le nombre de fois où une assertion a réussi ou échoué vous donne moins d’informations qu’une comparaison du résultat attendu avec le résultat obtenu.

J'ai récemment eu le même problème. J'ai combiné l'idée de compter les erreurs avec la mention de Assert.Multiple de Yann Trevin dans une méthode d'extension pour IEnumberable qui me permettait de faire des choses comme:

[Test]
public void TestEvenNumbers()
{
    int[] numbers = new int[] { 2, 4, 12, 22, 13, 42 };
    numbers.AssertAll((num) => Assert.That((num % 2) == 0, "{0} is an odd number", num));
}

Ce qui donne la sortie NUnit:

TestEvenNumbers:
  5 of 6 tests passed; 0 inconclusive
FAILED: 13:   13 is an odd number
  Expected: True
  But was:  False

  Expected: 6
  But was:  5

Et la solution au problème du PO serait:

[Test]
public void TestSelect()
{
    ids.AssertAll(CheckStoredProcedures);
}

private void CheckStoredProcedures(Id id)
{
    DataTable old = Database.call("old_stored_proc",id);
    DataTable new_ = Database.call("new_stored_proc",id);

    Assert.AreEqual(old.Rows[0]["column"], new_.Rows[0]["column"]);
}

Voici la méthode d'extension (notez que j'ai utilisé "Tous" au lieu de "Multiple" pour assurer la cohérence avec la terminologie Linq):

using System;
using System.Text;
using System.Collections.Generic;
using NUnit.Framework;

public static class NUnitExtensions
{
    public static void AssertAll<T>(this IEnumerable<T> objects, Action<T> test)
    {
        int total = 0;
        int passed = 0;
        int failed = 0;
        int inconclusive = 0;
        var sb = new StringBuilder();
        foreach (var obj in objects)
        {
            total++;
            try
            {
                test(obj);
                passed++;
            }
            catch (InconclusiveException assertion)
            {
                inconclusive++;
                string message = string.Format("INCONCLUSIVE: {0}: {1}", obj.ToString(), assertion.Message);
                Console.WriteLine(message);
                sb.AppendLine(message);
            }
            catch (AssertionException assertion)
            {
                failed++;
                string message = string.Format("FAILED: {0}: {1}", obj.ToString(), assertion.Message);
                Console.WriteLine(message);
                sb.AppendLine(message);
            }
        }

        if (passed != total)
        {
            string details = sb.ToString();
            string message = string.Format("{0} of {1} tests passed; {2} inconclusive\n{3}", passed, total, inconclusive, details);
            if (failed == 0)
            {
                Assert.Inconclusive(message);
            }
            else
            {
                Assert.AreEqual(total, passed, message);
            }
        }
    }
}

Vous pouvez utiliser [TestCase ()] attribut s'il s'agit d'une simple liste d'identifiants codés en dur.

[Test]
[TestCase(1234)]
[TestCase(5678)]
[TestCase(7654)]
public void TestSelect(int id)
{
    DataTable old = Database.call("old_stored_proc", id);
    DataTable new_ = Database.call("new_stored_proc", id);

    Assert.AreEqual(old.Rows[0]["column"], new_.Rows[0]["column"]);
}

Ceci générera trois tests distincts pour chaque ID et, quel que soit le programme d’analyse de test utilisé, affichera le nombre de réussites / échecs.

Si vous avez besoin de générer une liste dynamique d'identifiants, recommandez l'utilisation de [TestCaseSource ()] attribut .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top