สิ่งนี้ทำให้ฉันเข้าสู่การทดสอบหน่วยและทำให้ฉันมีความสุขมาก
เราเพิ่งเริ่มทำการทดสอบหน่วย เป็นเวลานานแล้วที่ฉันรู้ว่าการเริ่มทำมันเป็นเรื่องดี แต่ฉันไม่รู้ว่าจะเริ่มอย่างไรและที่สำคัญกว่านั้นจะต้องทดสอบอะไร
จากนั้นเราต้องเขียนโค้ดที่สำคัญในโปรแกรมบัญชีของเราใหม่ ส่วนนี้มีความซับซ้อนมากเนื่องจากเกี่ยวข้องกับสถานการณ์ต่างๆมากมาย ส่วนที่ฉันพูดถึงคือวิธีการชำระเงินการขายและ / หรือใบแจ้งหนี้การซื้อที่ป้อนไว้ในระบบบัญชีแล้ว
ฉันไม่รู้ว่าจะเริ่มเขียนโค้ดอย่างไรเนื่องจากมีตัวเลือกการชำระเงินที่แตกต่างกันมากมาย ใบแจ้งหนี้อาจเป็น $ 100 แต่ลูกค้าโอนเงินเพียง $ 99 บางทีคุณอาจส่งใบแจ้งหนี้การขายให้กับลูกค้า แต่คุณได้ซื้อจากลูกค้ารายนั้นด้วย คุณขายเขาในราคา 300 ดอลลาร์ แต่คุณซื้อมาในราคา 100 ดอลลาร์ คุณสามารถคาดหวังให้ลูกค้าของคุณจ่ายเงินให้คุณ $ 200 เพื่อชำระยอดคงเหลือ แล้วถ้าคุณขายได้ 500 เหรียญ แต่ลูกค้าจ่ายให้คุณแค่ 250 เหรียญ?
ดังนั้นฉันจึงมีปัญหาที่ซับซ้อนมากในการแก้ไขโดยมีความเป็นไปได้มากมายที่สถานการณ์หนึ่งจะทำงานได้อย่างสมบูรณ์แบบ แต่จะผิดกับชุดค่าผสมการเรียกเก็บเงิน / การชำระเงินประเภทอื่น
นี่คือจุดที่การทดสอบหน่วยมาช่วย
ฉันเริ่มเขียน (ในรหัสทดสอบ) วิธีสร้างรายการใบแจ้งหนี้ทั้งสำหรับการขายและการซื้อ จากนั้นฉันเขียนวิธีที่สองเพื่อสร้างการชำระเงินจริง โดยปกติผู้ใช้จะป้อนข้อมูลนั้นผ่านอินเทอร์เฟซผู้ใช้
จากนั้นฉันก็สร้าง TestMethod แรกโดยทดสอบการชำระเงินใบแจ้งหนี้ใบเดียวโดยไม่มีส่วนลดการชำระเงินใด ๆ การดำเนินการทั้งหมดในระบบจะเกิดขึ้นเมื่อการชำระเงินผ่านธนาคารจะถูกบันทึกลงในฐานข้อมูล อย่างที่คุณเห็นฉันสร้างใบแจ้งหนี้สร้างการชำระเงิน (ธุรกรรมธนาคาร) และบันทึกธุรกรรมลงในดิสก์ ในคำยืนยันของฉันฉันใส่ตัวเลขที่ถูกต้องที่ลงท้ายด้วยธุรกรรมธนาคารและในใบแจ้งหนี้ที่เชื่อมโยง ฉันตรวจสอบจำนวนการชำระเงินจำนวนเงินที่ชำระยอดส่วนลดและยอดคงเหลือของใบแจ้งหนี้หลังการทำธุรกรรม
หลังจากการทดสอบเสร็จสิ้นฉันจะไปที่ฐานข้อมูลและตรวจสอบอีกครั้งว่าสิ่งที่ฉันคาดหวังอยู่ที่นั่นหรือไม่
หลังจากเขียนแบบทดสอบแล้วฉันก็เริ่มเขียนโค้ดวิธีการชำระเงิน (ส่วนหนึ่งของคลาส BankHeader) ในการเขียนโค้ดฉันแค่ใส่ใจกับรหัสเพื่อให้ผ่านการทดสอบครั้งแรก ฉันยังไม่ได้คิดถึงสถานการณ์อื่นที่ซับซ้อนกว่านี้
ฉันทำการทดสอบครั้งแรกแก้ไขข้อบกพร่องเล็ก ๆ น้อย ๆ จนกว่าการทดสอบจะผ่านไป
จากนั้นฉันก็เริ่มเขียนการทดสอบครั้งที่สองคราวนี้ใช้ส่วนลดการชำระเงิน หลังจากเขียนแบบทดสอบแล้วฉันได้แก้ไขวิธีการชำระเงินเพื่อรองรับส่วนลด
ขณะทดสอบความถูกต้องด้วยส่วนลดการชำระเงินฉันยังทดสอบการชำระเงินแบบธรรมดา การทดสอบทั้งสองควรผ่านแน่นอน
จากนั้นฉันก็หาทางลงไปสู่สถานการณ์ที่ซับซ้อนมากขึ้น
1) คิดถึงสถานการณ์ใหม่
2) เขียนแบบทดสอบสำหรับสถานการณ์นั้น ๆ
3) ทำการทดสอบเดี่ยวนั้นเพื่อดูว่าจะผ่านหรือไม่
4) หากไม่ได้ฉันจะทำการดีบักและแก้ไขโค้ดจนกว่าจะผ่าน
5) ในขณะที่แก้ไขโค้ดฉันยังคงทำการทดสอบทั้งหมด
นี่คือวิธีที่ฉันจัดการเพื่อสร้างวิธีการชำระเงินที่ซับซ้อนมาก หากไม่มีการทดสอบหน่วยฉันไม่รู้ว่าจะเริ่มเขียนโค้ดอย่างไรปัญหาก็ดูเหมือนจะท่วมท้น ด้วยการทดสอบฉันสามารถเริ่มต้นด้วยวิธีง่ายๆและขยายทีละขั้นตอนโดยมั่นใจว่าสถานการณ์ที่ง่ายกว่านี้จะยังคงใช้งานได้
ฉันแน่ใจว่าการใช้การทดสอบหน่วยช่วยให้ฉันเข้ารหัสได้สองสามวัน (หรือหลายสัปดาห์) และเป็นการรับประกันความถูกต้องของวิธีการของฉันไม่มากก็น้อย
หากฉันคิดถึงสถานการณ์ใหม่ในภายหลังฉันสามารถเพิ่มลงในการทดสอบเพื่อดูว่าใช้งานได้หรือไม่ หากไม่สามารถแก้ไขโค้ดได้ แต่ต้องแน่ใจว่าสถานการณ์อื่น ๆ ยังคงทำงานได้อย่างถูกต้อง วิธีนี้จะช่วยประหยัดวันและเวลาในขั้นตอนการบำรุงรักษาและการแก้ไขข้อบกพร่อง
ใช่แม้แต่โค้ดที่ผ่านการทดสอบก็ยังมีข้อบกพร่องหากผู้ใช้ทำในสิ่งที่คุณไม่คิดหรือขัดขวางไม่ให้ทำ
ด้านล่างนี้เป็นเพียงการทดสอบบางส่วนที่ฉันสร้างขึ้นเพื่อทดสอบวิธีการชำระเงินของฉัน
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);
}