Dies brachte mich zum Testen von Einheiten und machte mich sehr glücklich
Wir haben gerade angefangen, Unit-Tests durchzuführen. Lange wusste ich, dass es gut sein würde, damit zu beginnen, aber ich hatte keine Ahnung, wie ich anfangen sollte und was noch wichtiger war, was ich testen sollte.
Dann mussten wir einen wichtigen Code in unser Buchhaltungsprogramm umschreiben. Dieser Teil war sehr komplex, da er viele verschiedene Szenarien beinhaltete. Der Teil, über den ich spreche, ist eine Methode zum Bezahlen von Verkaufs- und / oder Kaufrechnungen, die bereits in das Buchhaltungssystem eingegeben wurden.
Ich wusste einfach nicht, wie ich mit dem Codieren beginnen sollte, da es so viele verschiedene Zahlungsoptionen gab. Eine Rechnung könnte 100 US-Dollar betragen, aber der Kunde hat nur 99 US-Dollar überwiesen. Möglicherweise haben Sie Verkaufsrechnungen an einen Kunden gesendet, aber Sie haben auch bei diesem Kunden gekauft. Sie haben ihn also für 300 Dollar verkauft, aber für 100 Dollar gekauft. Sie können erwarten, dass Ihr Kunde Ihnen 200 US-Dollar zahlt, um den Restbetrag zu begleichen. Und was ist, wenn Sie für 500 US-Dollar verkauft haben, der Kunde Ihnen jedoch nur 250 US-Dollar zahlt?
Ich hatte also ein sehr komplexes Problem zu lösen, mit vielen Möglichkeiten, dass ein Szenario perfekt funktionieren würde, aber bei einer anderen Art von Invocie / Payment-Kombination falsch wäre.
Hier kamen Unit-Tests zum Einsatz.
Ich begann (innerhalb des Testcodes) eine Methode zu schreiben, um eine Liste von Rechnungen sowohl für Verkäufe als auch für Einkäufe zu erstellen. Dann habe ich eine zweite Methode geschrieben, um die tatsächliche Zahlung zu erstellen. Normalerweise würde ein Benutzer diese Informationen über eine Benutzeroberfläche eingeben.
Dann habe ich die erste Testmethode erstellt, bei der eine sehr einfache Zahlung einer einzelnen Rechnung ohne Zahlungsrabatte getestet wurde. Alle Aktionen im System würden ausgeführt, wenn eine Bankzahlung in der Datenbank gespeichert würde. Wie Sie sehen, habe ich eine Rechnung erstellt, eine Zahlung (eine Banküberweisung) erstellt und die Transaktion auf der Festplatte gespeichert. In meinen Behauptungen habe ich die richtigen Zahlen angegeben, die in der Banküberweisung und in der verknüpften Rechnung landen. Ich überprüfe nach der Transaktion die Anzahl der Zahlungen, die Zahlungsbeträge, den Rabattbetrag und den Restbetrag der Rechnung.
Nachdem der Test ausgeführt wurde, ging ich zur Datenbank und überprüfte noch einmal, ob das, was ich erwartet hatte, dort war.
Nachdem ich den Test geschrieben hatte, begann ich mit der Codierung der Zahlungsmethode (Teil der BankHeader-Klasse). In der Codierung habe ich mich nur mit Code beschäftigt, um den ersten Test zu bestehen. Ich habe noch nicht über die anderen, komplexeren Szenarien nachgedacht.
Ich habe den ersten Test ausgeführt und einen kleinen Fehler behoben, bis mein Test bestanden wurde.
Dann fing ich an, den zweiten Test zu schreiben, diesmal mit einem Zahlungsrabatt. Nachdem ich den Test geschrieben habe, habe ich die Zahlungsmethode geändert, um Rabatte zu unterstützen.
Beim Testen der Richtigkeit mit einem Zahlungsrabatt habe ich auch die einfache Zahlung getestet. Beide Tests sollten natürlich bestehen.
Dann arbeitete ich mich zu den komplexeren Szenarien hinunter.
1) Stellen Sie sich ein neues Szenario vor
2) Schreiben Sie einen Test für dieses Szenario
3) Führen Sie diesen einzelnen Test durch, um festzustellen, ob er bestanden wird
4) Wenn dies nicht der Fall wäre, würde ich den Code debuggen und ändern, bis er erfolgreich ist.
5) Während ich den Code änderte, führte ich alle Tests weiter aus
So gelang es mir, meine sehr komplexe Zahlungsmethode zu erstellen. Ohne Unit-Tests wusste ich nicht, wie ich mit dem Codieren beginnen sollte. Das Problem schien überwältigend. Beim Testen könnte ich mit einer einfachen Methode beginnen und sie Schritt für Schritt erweitern, mit der Gewissheit, dass die einfacheren Szenarien immer noch funktionieren würden.
Ich bin sicher, dass mir die Verwendung von Unit-Tests einige Tage (oder Wochen) an Codierung erspart hat und mehr oder weniger die Richtigkeit meiner Methode garantiert.
Wenn ich später an ein neues Szenario denke, kann ich es einfach zu den Tests hinzufügen, um zu sehen, ob es funktioniert oder nicht. Wenn nicht, kann ich den Code ändern, aber trotzdem sicherstellen, dass die anderen Szenarien immer noch ordnungsgemäß funktionieren. Dies spart Tage und Tage in der Wartungs- und Fehlerbehebungsphase.
Ja, selbst getesteter Code kann immer noch Fehler aufweisen, wenn ein Benutzer Dinge tut, an die Sie nicht gedacht haben oder die ihn daran gehindert haben
Im Folgenden sind nur einige Tests aufgeführt, die ich zum Testen meiner Zahlungsmethode erstellt habe.
public class TestPayments
{
InvoiceDiaryHeader invoiceHeader = null;
InvoiceDiaryDetail invoiceDetail = null;
BankCashDiaryHeader bankHeader = null;
BankCashDiaryDetail bankDetail = null;
public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date)
{
......
......
}
public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount)
{
......
......
......
}
[TestMethod]
public void TestSingleSalesPaymentNoDiscount()
{
IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
list.Add(CreateSales("119", true, 1, "01-09-2008"));
bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0);
bankHeader.Save();
Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
}
[TestMethod]
public void TestSingleSalesPaymentDiscount()
{
IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
list.Add(CreateSales("119", true, 2, "01-09-2008"));
bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M);
bankHeader.Save();
Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
}
[TestMethod]
[ExpectedException(typeof(ApplicationException))]
public void TestDuplicateInvoiceNumber()
{
IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
list.Add(CreateSales("100", true, 2, "01-09-2008"));
list.Add(CreateSales("200", true, 2, "01-09-2008"));
bankHeader = CreateMultiplePayments(list, 3, 300, 0);
bankHeader.Save();
Assert.Fail("expected an ApplicationException");
}
[TestMethod]
public void TestMultipleSalesPaymentWithPaymentDiscount()
{
IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
list.Add(CreateSales("119", true, 11, "01-09-2008"));
list.Add(CreateSales("400", true, 12, "02-09-2008"));
list.Add(CreateSales("600", true, 13, "03-09-2008"));
list.Add(CreateSales("25,40", true, 14, "04-09-2008"));
bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M);
bankHeader.Save();
Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count);
Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount);
Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount);
Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
}
[TestMethod]
public void TestSettlement()
{
IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales
list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase
bankHeader = CreateMultiplePayments(list, 22, 200, 0);
bankHeader.Save();
Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count);
Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
}