Question

J'ai une classe qui traite 2 fichiers XML et produit un fichier texte.

J'aimerais rédiger un ensemble de tests unitaires / d'intégration pouvant réussir ou échouer individuellement pour cette classe, dont les caractéristiques sont les suivantes:

  1. Pour les entrées A et B, générez la sortie.
  2. Comparez le contenu du fichier généré à la sortie attendue du contenu
  3. Lorsque le contenu réel diffère du contenu attendu, échouez et affichez des informations utiles sur les différences.

Ci-dessous, le prototype de la classe avec mon premier essai aux tests unitaires.

Existe-t-il un motif que je devrais utiliser pour ce type de test ou les gens ont-ils tendance à écrire des zillions de fonctions TestX ()?

Existe-t-il une meilleure méthode pour amadouer les différences entre les fichiers texte et NUnit? Devrais-je intégrer un algorithme diff de fichier texte?

class ReportGenerator
{
    string Generate(string inputPathA, string inputPathB)
    {
        //do stuff
    }
}
[TextFixture]
public class ReportGeneratorTests
{
     static Diff(string pathToExpectedResult, string pathToActualResult)
     {
         using (StreamReader rs1 = File.OpenText(pathToExpectedResult))
         {
             using (StreamReader rs2 = File.OpenText(pathToActualResult))
             {
                 string actualContents = rs2.ReadToEnd();
                 string expectedContents = rs1.ReadToEnd();                  

                 //this works, but the output could be a LOT more useful.
                 Assert.AreEqual(expectedContents, actualContents);
             }
         }
     }

     static TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
     {
          ReportGenerator obj = new ReportGenerator();
          string pathToResult = obj.Generate(pathToInputA, pathToInputB);
          Diff(pathToExpectedResult, pathToResult);
     }

     [Test]
     public void TestX()
     {
          TestGenerate("x1.xml", "x2.xml", "x-expected.txt");
     }

     [Test]
     public void TestY()
     {
          TestGenerate("y1.xml", "y2.xml", "y-expected.txt");
     }

     //etc...
}

Mettre à jour

Je ne suis pas intéressé par le test de la fonctionnalité diff. Je veux juste l'utiliser pour produire des échecs plus lisibles.

Était-ce utile?

La solution

Comme pour les tests multiples avec des données différentes, utilisez l’extension NUnit RowTest:

using NUnit.Framework.Extensions;

[RowTest]
[Row("x1.xml", "x2.xml", "x-expected.xml")]
[Row("y1.xml", "y2.xml", "y-expected.xml")]
public void TestGenerate(string pathToInputA, string pathToInputB, string pathToExpectedResult)
 {
      ReportGenerator obj = new ReportGenerator();
      string pathToResult = obj.Generate(pathToInputA, pathToInputB);
      Diff(pathToExpectedResult, pathToResult);
 }

Autres conseils

Vous demandez probablement les tests contre "or". Les données. Je ne sais pas s'il existe un terme spécifique pour ce type de test accepté dans le monde entier, mais c'est ainsi que nous procédons.

Créer une classe de fixture de base. Il a en gros "void DoTest (string fileName)", qui lira un fichier spécifique en mémoire, exécutera une méthode de transformation abstraite "string Transform (string text)", puis lira fileName.gold du même endroit et comparera le texte transformé. avec ce qui était attendu. Si le contenu est différent, il lève une exception. L'exception levée contient le numéro de ligne de la première différence ainsi que le texte de la ligne attendue et réelle. Le texte étant stable, il s’agit généralement d’informations suffisantes pour détecter immédiatement le problème. Veillez à marquer les lignes avec " Expected: " et "Réel:" ou vous devinerez toujours lequel est ce qui, en regardant les résultats du test.

Ensuite, vous aurez des montages de test spécifiques, dans lesquels vous implémenterez la méthode Transform qui fait le bon travail, puis des tests qui ressemblent à ceci:

[Test] public void TestX() { DoTest("X"); }
[Test] public void TestY() { DoTest("Y"); }

Le nom du test ayant échoué vous indiquera instantanément ce qui est cassé. Bien sûr, vous pouvez utiliser le test de ligne pour regrouper des tests similaires. Avoir des tests séparés est également utile dans un certain nombre de situations, comme ignorer des tests, communiquer des tests à des collègues, etc. Ce n'est pas un problème de créer un extrait de code qui créera un test pour vous en une seconde. Vous passerez beaucoup plus de temps à préparer les données.

Ensuite, vous aurez également besoin de quelques données de test et, pour que votre appareil de base le trouve, assurez-vous de définir des règles à ce sujet pour le projet. Si le test échoue, videz la sortie réelle dans le fichier proche de l'or et effacez-la si le test réussit. De cette façon, vous pouvez utiliser l'outil de diff en cas de besoin. Lorsque aucune donnée or n’a été trouvée, le test échoue avec le message approprié, mais la sortie réelle est écrite de toute façon, vous pouvez donc vérifier qu’elle est correcte et la copier pour devenir "or".

J'écrirais probablement un test unitaire contenant une boucle. À l'intérieur de la boucle, je lisais 2 fichiers XML et un fichier diff, puis diffaisais les fichiers xml (sans l'écrire sur le disque) et le comparais au fichier diff lu à partir du disque. Les fichiers seraient numérotés, par exemple a1.xml, b1.xml, diff1.txt; a2.xml, b2.xml, diff2.txt; a3.xml, b3.xml, diff3.txt, etc., et la boucle s’arrête quand elle ne trouve pas le nombre suivant.

Ensuite, vous pouvez écrire de nouveaux tests en ajoutant simplement de nouveaux fichiers texte.

Plutôt que d’appeler .AreEqual, vous pouvez analyser vous-même les deux flux d’entrée, conserver un nombre de lignes et de colonnes et en comparer le contenu. Dès que vous trouvez une différence, vous pouvez générer un message tel que ...

  

Ligne 32 colonne 12 - Trouvé 'x' quand 'y' était attendu

Vous pouvez éventuellement améliorer cela en affichant plusieurs lignes de sortie

  

Différence à la ligne 32, colonne 12, première différence montrée
  A = ceci est un x st
  B = c'est un e m

Remarque: en règle générale, je ne générerais généralement que par mon code l'un des deux flux que vous avez. L’autre, je le prendrais dans un fichier test / texte, après avoir vérifié à l’œil ou par une autre méthode que les données contenues étaient correctes!

J'utiliserais probablement XmlReader pour parcourir les fichiers et les comparer. Lorsque je distingue une différence, je affiche un XPath à l’emplacement où les fichiers sont différents.

PS: Mais en réalité, cela me suffisait toujours de faire une simple lecture du fichier entier en chaîne et de comparer les deux chaînes. Pour le rapport, il suffit de voir que le test a échoué. Ensuite, lorsque je fais le débogage, je diffère généralement les fichiers à l'aide de Araxis Merge pour savoir où exactement. J'ai des problèmes.

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