Frage

In dem Buch The Art of Unit Testing es spricht über den Wunsch, wartbar zu schaffen und lesbares Komponententests. Rund 204 Seite erwähnt, dass man sollte versuchen, mehr in einem Test zu vermeiden behauptet und vielleicht Objekte mit einer überschriebenen Methode Equals vergleichen. Dies funktioniert gut, wenn wir nur ein Objekt haben die erwarteten vs. tatsächlichen Ergebnisse zu vergleichen. Doch was passiert, wenn wir eine Liste (oder Sammlung) der Objekte.

Betrachten Sie den Test unten. Ich habe mehr als eine Assertion. In der Tat gibt es zwei separate Schleifen Aufruf behauptet. In diesem Fall werde ich bis mit 5 Behauptungen beenden. 2 den Inhalt einer Liste existiert in einem anderen, und 2 umgekehrt zu überprüfen. Die 5. Vergleich der Anzahl der Elemente in den Listen.

Wenn jemand Vorschläge hat diesen Test zu verbessern, bin ich ganz Ohr. Ich verwende MSTest im Moment, obwohl ich MSTest des Assert mit NUnits für die fließend API (Assert.That) ersetzt.

Aktuelle Überarbeitete Code:

        [TestMethod]
#if !NUNIT 
        [HostType("Moles")]
#else
        [Moled]
#endif
        public void LoadCSVBillOfMaterials_WithCorrectCSVFile_ReturnsListOfCSVBillOfMaterialsThatMatchesInput()
        {
            //arrange object(s)            
            var filePath = "Path Does Not Matter Because of Mole in File object";
            string[] csvDataCorrectlyFormatted = { "1000, 1, Alt 1, , TBD, 1, 10.0, Notes, , Description, 2.50, ,A",
                                                   "1001, 1, Alt 2, , TBD, 1, 10.0, Notes, , Description, 2.50, ,A" };

            var materialsExpected = new List<CSVMaterial>();
            materialsExpected.Add(new CSVMaterial("1000", 1, "Alt 1", "TBD", 1m, 10.0m, "Notes", "Description", 2.50m,"A"));
            materialsExpected.Add(new CSVMaterial("1001", 1, "Alt 2", "TBD", 1m, 10.0m, "Notes", "Description", 2.50m,"A"));

            //by-pass actually hitting the file system and use in-memory representation of CSV file
            MFile.ReadAllLinesString = s => csvDataCorrectlyFormatted;

            //act on object(s)                        
            var materialsActual = modCSVImport.LoadCSVBillOfMaterials(filePath);

            //assert something happended            
            Assert.That(materialsActual.Count,Is.EqualTo(materialsExpected.Count));
            materialsExpected.ForEach((anExpectedMaterial) => Assert.That(materialsActual.Contains(anExpectedMaterial)));
            materialsActual.ForEach((anActualMaterial) => Assert.That(materialsExpected.Contains(anActualMaterial)));
        }

Original Multi-Assert Unit-Test:

 ...
            //1st element
            Assert.AreEqual("1000", materials[0].PartNumber);
            Assert.AreEqual(1, materials[0].SequentialItemNumber);
            Assert.AreEqual("Alt 1", materials[0].AltPartNumber);
            Assert.AreEqual("TBD", materials[0].VendorCode);
            Assert.AreEqual(1m, materials[0].Quantity);
            Assert.AreEqual(10.0m, materials[0].PartWeight);
            Assert.AreEqual("Notes", materials[0].PartNotes);
            Assert.AreEqual("Description", materials[0].PartDescription);
            Assert.AreEqual(2.50m, materials[0].UnitCost);
            Assert.AreEqual("A", materials[1].Revision);
            //2nd element
            Assert.AreEqual("1001", materials[1].PartNumber);
            Assert.AreEqual(1, materials[1].SequentialItemNumber);
            Assert.AreEqual("Alt 2", materials[1].AltPartNumber);
            Assert.AreEqual("TBD", materials[1].VendorCode);
            Assert.AreEqual(1m, materials[1].Quantity);
            Assert.AreEqual(10.0m, materials[1].PartWeight);
            Assert.AreEqual("Notes", materials[1].PartNotes);
            Assert.AreEqual("Description", materials[1].PartDescription);
            Assert.AreEqual(2.50m, materials[1].UnitCost);
            Assert.AreEqual("A", materials[1].Revision);
        }
War es hilfreich?

Lösung

Ich habe häufig mehr als eine Behauptung. Wenn es ist alles Teil eine logische Arbeitseinheit zu testen, ich sehe kein Problem.

Nun, ich tun einig, dass, wenn Sie einen Typ haben, die Equals überschreibt, dass die Tests viel einfacher als Ihre zweite Form macht. Aber in Ihrem ersten Test, sieht es Ihnen wirklich wollen einfach nur behaupten, dass die resultierende Sammlung gleich ein einen erwartet. Ich denke, dass logisch eine Behauptung ist - es ist nur, dass derzeit mehrere Mini-Behauptungen Leistung erbringt, es zu testen

.

haben einige Unit-Test-Frameworks Methoden zu testen, ob zwei Sammlungen gleich sind - und wenn die, die Sie verwenden nicht der Fall, können Sie ganz einfach ein schreiben. Ich habe vor kurzem genau dies in meinem "Neuimplementierung LINQ to Objekte“Blog-Serie , denn obwohl NUnit eine Hilfsmethode bietet, seine Diagnose nicht sehr hilfreich ist. Ich Refactoring den Code aus MoreLINQ sehr leicht, im Grunde.

Andere Tipps

Dies ist das Refactoring ich zur Zeit verwenden. Ich overrode die ToString() Methode der CSVMaterial und hat eine nützlichere assert Nachricht. Deshalb denke ich, hilft dies mit Code Lesbarkeit und Wartbarkeit. Es macht auch die Unit-Test vertrauenswürdig (aufgrund der hilfreichen Fehlermeldung).

Und Jon, vielen Dank für die Gedanken über eine logische Arbeitseinheit. Mein Refactoring Code macht über die gleiche Sache wie die vorherige Iteration. Beide testen noch eine logische Sache. Außerdem werde ich in die MoreLINQ Sachen suchen. Wenn es in Ihrem C # InDepth 2. Auflage Buch ist, werde ich über sie kommen, wie ich die MEAP-Version von Manning gekauft. Vielen Dank für Ihre Hilfe.

public void LoadCSVBillOfMaterials_WithCorrectCSVFile_ReturnsListOfCSVBillOfMaterialsThatMatchesInput()
{
    //arrange object(s)            
    var filePath = "Path Does Not Matter Because of Mole in File object";
    string[] csvDataCorrectlyFormatted = { "1000, 1, Alt 1, , TBD, 1, 10.0, Notes, , Description, 2.50, ,A",
                                           "1001, 1, Alt 2, , TBD, 1, 10.0, Notes, , Description, 2.50, ,A" };            

    var materialsExpected = new List<CSVMaterial>();
    materialsExpected.Add(new CSVMaterial("1001", 1, "Alt 1", "TBD", 1m, 10.0m, "Notes", "Description", 2.50m,"A"));
    materialsExpected.Add(new CSVMaterial("1001", 1, "Alt 2", "TBD", 1m, 10.0m, "Notes", "Description", 2.50m,"A"));           

    //by-pass actually hitting the file system and use in-memory representation of CSV file
    MFile.ReadAllLinesString = s => csvDataCorrectlyFormatted;

    //act on object(s)                        
    var materialsActual = modCSVImport.LoadCSVBillOfMaterials(filePath);

    //assert something happended            

    //Setup message for failed asserts
    var assertMessage = new StringBuilder();
    assertMessage.AppendLine("Actual Materials:");
    materialsActual.ForEach((m) => assertMessage.AppendLine(m.ToString()));
    assertMessage.AppendLine("Expected Materials:");
    materialsExpected.ForEach((m) => assertMessage.AppendLine(m.ToString()));

    Assert.That(materialsActual, Is.EquivalentTo(materialsExpected),assertMessage.ToString());
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top