2008-10-03 9 views
6

On m'a demandé d'écrire une application de test qui doit tester une nouvelle procédure stockée sur plusieurs lignes dans une base de données, en substance, je veux faire quelque chose comme ceci:NUnit: L'exécution de plusieurs assertions dans un seul test

 

[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 1 ligne ne correspond pas à l'autre, le test complet échoue; Au lieu de cela je voudrais compter combien de fois l'assertion a été passée et combien de fois elle a échoué. Y a-t-il un moyen de le faire avec NUnit? Je me rends compte que NUnit pourrait être exagéré et c'est une tâche simple sans cela ... Je voulais juste l'apprendre. ;)

Répondre

5

1) Si les id sont constants et non regardé à l'exécution test de temps , créez un appareil de test unitaire distinct pour chaque ID. De cette façon, vous saurez quels identifiants échouent réellement. Voir ici pour une écriture sur les problèmes de données des tests chasserai
http://googletesting.blogspot.com/2008/09/tott-data-driven-traps.html

2) Si vous avez besoin de regarder dynamiquement faire de l'identifiant qu'il est impossible de créer un appareil pour chaque identifiant, la suggestion de l'utilisation Akmad avec un seul changement. Conservez une liste des ID dont les valeurs ne sont pas identiques et ajoutez la liste au message d'erreur. Il sera extrêmement difficile de diagnostiquer un test qui n'indique que le nombre d'erreurs, car vous ne saurez pas quels identifiants causent les erreurs. 3) Je ne sais pas à quel point il serait difficile de le 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 dynamiquement des tests et les attachons à la classe TestCase afin que nous avons un test échoué pour chaque donnée qui ne passe pas. Bien que j'imagine que ce serait beaucoup plus difficile sans les capacités dynamiques de Python.

+0

Merci, ce que je cherchais vraiment était votre # 3 ... mais comme vous l'avez dit ... c'est .net :( – mmattax

0

Eh bien, vous pouvez déclarer un compteur puis affirmer la valeur du compteur pour déterminer pass/fail

En outre, vous pouvez faire le gros du travail dans la configuration de test, puis il suffit de créer plusieurs tests .

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

+0

Je veux affirmer que la procédure stockée fonctionne pour chaque ligne de la base de données. – mmattax

1

Je compterais le nombre de lignes qui ne correspond pas et écrirais alors une assertion qui comparera ce nombre avec 0 et renverrait le nombre de chaînes non assorties 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.

9

On dirait que vous ne faites qu'affirmer la mauvaise chose. Si vous voulez vérifier toutes les valeurs et affirmer qu'il n'y a pas d'erreurs (ou afficher le nombre d'erreurs) puis 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."); 
} 
0

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 qu'une assertion réussit ou échoue vous donne moins d'informations qu'une comparaison du résultat que vous attendiez avec le résultat que vous avez obtenu.

4

Je sais que la question est spécifiquement à propos de NUnit, mais de façon intéressante, Gallio/MbUnit a une fonctionnalité qui permet d'exécuter et d'attraper plusieurs assertions à la fois.

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

Le Assert.Multiple rattrape toutes les assertions défaillantes et va leur rapport à la fin de l'essai.

0

J'ai récemment eu le même problème. Je combiné l'idée de compter les erreurs avec la mention de Yann Trevin de Assert.Multiple dans une méthode d'extension pour IEnumberable qui me permet 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)); 
} 

qui se traduit par 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 de l'OP 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 je « Tous » au lieu de « multiples » pour 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); 
      } 
     } 
    } 
} 
Questions connexes