Bu beni birim testine soktu ve beni çok mutlu etti
Birim testi yapmaya yeni başladık. Uzun zamandır bunu yapmaya başlamanın iyi olacağını biliyordum ama nasıl başlayacağımı ve daha da önemlisi neyi test edeceğimi bilmiyordum.
Sonra muhasebe programımızda önemli bir kodu yeniden yazmak zorunda kaldık. Bu bölüm, birçok farklı senaryo içerdiği için çok karmaşıktı. Bahsettiğim kısım, muhasebe sistemine zaten girilmiş olan satış ve / veya satın alma faturalarını ödeme yöntemidir.
Pek çok farklı ödeme seçeneği olduğu için kodlamaya nasıl başlayacağımı bilmiyordum. Fatura 100 $ olabilir, ancak müşteri yalnızca 99 $ transfer etti. Belki bir müşteriye satış faturaları göndermişsinizdir, ancak o müşteriden de satın almışsınızdır. Yani onu 300 dolara sattın ama 100 dolara aldın. Müşterinizin bakiyeyi kapatmak için size 200 $ ödemesini bekleyebilirsiniz. Ya 500 dolara sattıysan ama müşteri sana sadece 250 dolar öderse?
Bu yüzden, bir senaryonun mükemmel çalışacağı, ancak diğer türden bir fatura / ödeme kombinasyonunda yanlış olacağı birçok olasılıkla çözmem gereken çok karmaşık bir problem vardı.
Burası birim testinin kurtarmaya geldiği yer.
Hem satışlar hem de satın almalar için fatura listesi oluşturmak için bir yöntem (test kodunun içinde) yazmaya başladım. Sonra asıl ödemeyi oluşturmak için ikinci bir yöntem yazdım. Normalde bir kullanıcı bu bilgiyi bir kullanıcı arayüzü aracılığıyla girer.
Sonra, herhangi bir ödeme indirimi olmaksızın tek bir faturanın çok basit bir ödemesini test eden ilk TestMethod'u oluşturdum. Sistemdeki tüm eylem, bir banka ödemesi veritabanına kaydedildiğinde gerçekleşir. Gördüğünüz gibi bir fatura oluşturdum, bir ödeme (banka işlemi) oluşturdum ve işlemi diske kaydettim. İddialarımda, Banka işleminde ve bağlantılı Faturada biten doğru numaraların ne olması gerektiğini yazıyorum. İşlem sonrası ödeme adedini, ödeme tutarını, indirim tutarını ve fatura bakiyesini kontrol ediyorum.
Test çalıştırıldıktan sonra veritabanına gidip beklediğim şeyin orada olup olmadığını iki kez kontrol ettim.
SonraTesti yazdıktan , ödeme yöntemini (BankHeader sınıfının bir parçası) kodlamaya başladım. Kodlamada ilk testi geçmek için sadece kodla uğraştım. Henüz diğer, daha karmaşık senaryolar hakkında düşünmedim.
İlk testi yaptım, testim geçene kadar küçük bir hatayı düzelttim.
Sonra ikinci testi yazmaya başladım, bu sefer bir ödeme indirimi ile çalışarak. Testi yazdıktan sonra indirimleri desteklemek için ödeme yöntemini değiştirdim.
Bir ödeme indirimi ile doğruluğu test ederken, basit ödemeyi de test ettim. Elbette her iki test de geçmelidir.
Sonra daha karmaşık senaryolara doğru ilerledim.
1) Yeni bir senaryo düşünün
2) Bu senaryo için bir test yazın
3) Geçip geçmeyeceğini görmek için o tek testi çalıştırın
4) Yapmasaydı, kodu geçene kadar hata ayıklayıp değiştirirdim.
5) Kodu değiştirirken tüm testleri çalıştırmaya devam ettim
Çok karmaşık ödeme yöntemimi bu şekilde oluşturmayı başardım. Birim testi olmadan kodlamaya nasıl başlayacağımı bilmiyordum, sorun çok zor görünüyordu. Test ile basit bir yöntemle başlayabilir ve daha basit senaryoların hala işe yarayacağına dair güvence ile bunu adım adım genişletebilirim.
Birim testini kullanmanın birkaç gün (veya hafta) kodlamadan tasarruf ettiğinden ve yöntemimin doğruluğunu az çok garanti ettiğinden eminim.
Daha sonra yeni bir senaryo düşünürsem, çalışıp çalışmadığını görmek için onu testlere ekleyebilirim. Değilse, kodu değiştirebilirim, ancak yine de diğer senaryoların doğru şekilde çalıştığından emin olabilirim. Bu, bakım ve hata düzeltme aşamasında günlerden ve günlerden tasarruf sağlayacaktır.
Evet, bir kullanıcı sizin düşünmediğiniz veya yapmasını engellemediğiniz şeyler yaparsa, test edilen kodda bile hatalar olabilir.
Aşağıda, ödeme yöntemimi test etmek için oluşturduğum testlerden bazıları verilmiştir.
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);
}