it-swarm-vi.tech

Làm thế nào để bạn biết những gì để kiểm tra khi viết bài kiểm tra đơn vị?

Sử dụng C #, tôi cần một lớp có tên User có tên người dùng, mật khẩu, cờ hoạt động, tên, họ, tên đầy đủ, v.v.

Cần có các phương thức để xác thực một người dùng. Tôi chỉ cần viết một bài kiểm tra cho các phương pháp? Và tôi thậm chí có cần phải lo lắng về việc kiểm tra các thuộc tính vì chúng là getter và setters của .Net không?

127
Mike Roosa

Nhiều câu trả lời tuyệt vời cho câu hỏi này cũng nằm trong câu hỏi của tôi: " Bắt đầu TDD - Thách thức? Giải pháp? Đề xuất? "

Tôi có thể khuyên bạn nên xem bài đăng trên blog (một phần lấy cảm hứng từ câu hỏi của tôi), tôi đã nhận được một số phản hồi tốt về điều đó. Cụ thể là:

Tôi không biết bắt đầu từ đâu?

  • Làm trở lại việc gì. Chỉ nghĩ về việc viết bài kiểm tra khi bạn đang viết mã mới. Điều này có thể làm việc lại mã cũ hoặc một tính năng hoàn toàn mới.
  • Bắt đầu đơn giản. Donith chạy đi và cố gắng để có được một khuôn khổ thử nghiệm cũng như TDD-esque. Gỡ lỗi.Assert hoạt động tốt. Sử dụng nó như một điểm khởi đầu. Nó không lộn xộn với dự án của bạn hoặc tạo ra sự phụ thuộc.
  • Bắt đầu tích cực. Bạn đang cố gắng cải thiện nghề của bạn, cảm thấy tốt về nó. Tôi đã thấy rất nhiều nhà phát triển ngoài đó rất vui khi trì trệ và không thử những điều mới để cải thiện bản thân. Bạn đang làm điều đúng đắn, hãy nhớ điều này và nó sẽ giúp ngăn bạn từ bỏ.
  • Bắt đầu sẵn sàng cho một thử thách. Nó là khá khó để bắt đầu vào thử nghiệm. Mong đợi một thử thách, nhưng hãy nhớ - những thách thức có thể vượt qua.

Chỉ kiểm tra những gì bạn mong đợi

Tôi đã gặp vấn đề thực sự khi mới bắt đầu vì tôi thường xuyên ngồi đó cố gắng tìm ra mọi vấn đề có thể xảy ra và sau đó cố gắng kiểm tra và khắc phục. Đây là một cách nhanh chóng để đau đầu. Kiểm tra phải là một quá trình YAGNI thực sự. Nếu bạn biết có một vấn đề, sau đó viết một bài kiểm tra cho nó. Nếu không, don làm phiền.

Chỉ kiểm tra một điều

Mỗi trường hợp kiểm tra chỉ nên kiểm tra một điều. Nếu bạn thấy mình đặt tên và tên trong trường hợp thử nghiệm, thì bạn đã làm điều gì đó sai.

Tôi hy vọng điều này có nghĩa là chúng ta có thể chuyển từ "getters and setters" :)

130
Rob Cooper

Kiểm tra mã của bạn, không phải ngôn ngữ.

Một bài kiểm tra đơn vị như:

Integer i = new Integer(7);
assert (i.instanceOf(integer));

chỉ hữu ích nếu bạn đang viết trình biên dịch và có khả năng khác không là phương thức instanceof của bạn không hoạt động.

Đừng kiểm tra những thứ mà bạn có thể dựa vào ngôn ngữ để thực thi. Trong trường hợp của bạn, tôi tập trung vào các phương thức xác thực và lưu của bạn - và tôi sẽ viết các bài kiểm tra để đảm bảo rằng chúng có thể xử lý các giá trị null trong bất kỳ hoặc tất cả các trường đó một cách duyên dáng.

63
Tim Howland

Điều này đã đưa tôi vào thử nghiệm đơn vị và nó làm tôi rất hạnh phúc

Chúng tôi chỉ mới bắt đầu làm thử nghiệm đơn vị. Trong một thời gian dài, tôi biết sẽ tốt khi bắt đầu thực hiện nhưng tôi không biết bắt đầu như thế nào và quan trọng hơn là phải kiểm tra cái gì.

Sau đó, chúng tôi đã phải viết lại một đoạn mã quan trọng trong chương trình kế toán của chúng tôi. Phần này rất phức tạp vì nó liên quan đến rất nhiều tình huống khác nhau. Phần tôi đang nói đến là một phương thức thanh toán hóa đơn bán hàng và/hoặc mua hàng đã được nhập vào hệ thống kế toán.

Tôi chỉ không biết làm thế nào để bắt đầu mã hóa nó, vì có rất nhiều lựa chọn thanh toán khác nhau. Hóa đơn có thể là 100 đô la nhưng khách hàng chỉ chuyển 99 đô la. Có thể bạn đã gửi hóa đơn bán hàng cho một khách hàng nhưng bạn cũng đã mua từ khách hàng đó. Vì vậy, bạn đã bán anh ta với giá 300 đô la nhưng bạn đã mua với giá 100 đô la. Bạn có thể mong đợi khách hàng của bạn trả cho bạn 200 đô la để giải quyết số dư. Và nếu bạn bán được 500 đô la nhưng khách hàng chỉ trả cho bạn 250 đô la thì sao?

Vì vậy, tôi đã có một vấn đề rất phức tạp để giải quyết với nhiều khả năng rằng một kịch bản sẽ hoạt động hoàn hảo nhưng sẽ sai đối với một loại kết hợp thanh toán/thanh toán khác.

Đây là nơi thử nghiệm đơn vị đã đến giải cứu.

Tôi bắt đầu viết (bên trong mã kiểm tra) một phương pháp để tạo danh sách hóa đơn, cả cho bán hàng và mua hàng. Sau đó, tôi đã viết một phương thức thứ hai để tạo ra khoản thanh toán thực tế. Thông thường người dùng sẽ nhập thông tin đó thông qua giao diện người dùng.

Sau đó, tôi đã tạo TestMethod đầu tiên, thử nghiệm thanh toán rất đơn giản cho một hóa đơn mà không có bất kỳ khoản chiết khấu thanh toán nào. Tất cả các hành động trong hệ thống sẽ xảy ra khi một khoản thanh toán ngân hàng sẽ được lưu vào cơ sở dữ liệu. Như bạn có thể thấy tôi đã tạo hóa đơn, tạo thanh toán (giao dịch ngân hàng) và lưu giao dịch vào đĩa. Trong các xác nhận của mình, tôi đặt số nào phải là số chính xác kết thúc trong giao dịch Ngân hàng và Hóa đơn được liên kết. Tôi kiểm tra số lượng thanh toán, số tiền thanh toán, số tiền chiết khấu và số dư của hóa đơn sau khi giao dịch.

Sau khi chạy thử, tôi sẽ vào cơ sở dữ liệu và kiểm tra lại xem những gì tôi mong đợi có ở đó không.

Sa Tôi đã viết bài kiểm tra, tôi bắt đầu mã hóa phương thức thanh toán (một phần của lớp BankHeader). Trong mã hóa tôi chỉ bận tâm với mã để thực hiện bài kiểm tra đầu tiên. Tôi chưa nghĩ về các kịch bản khác, phức tạp hơn.

Tôi đã chạy thử nghiệm đầu tiên, sửa một lỗi nhỏ cho đến khi thử nghiệm của tôi vượt qua.

Sau đó, tôi bắt đầu viết bài kiểm tra thứ hai, lần này làm việc với chiết khấu thanh toán. Sau khi tôi viết bài kiểm tra, tôi đã sửa đổi phương thức thanh toán để hỗ trợ giảm giá.

Trong khi kiểm tra tính chính xác với chiết khấu thanh toán, tôi cũng đã thử nghiệm thanh toán đơn giản. Tất cả các bài kiểm tra nên vượt qua tất nhiên.

Sau đó, tôi tìm đường đến những tình huống phức tạp hơn.

1) Nghĩ về một kịch bản mới

2) Viết một bài kiểm tra cho kịch bản đó

3) Chạy thử nghiệm đơn đó để xem nó có vượt qua không

4) Nếu nó không gỡ lỗi và sửa đổi mã cho đến khi nó vượt qua.

5) Trong khi sửa đổi mã, tôi tiếp tục chạy tất cả các bài kiểm tra

Đây là cách tôi quản lý để tạo phương thức thanh toán rất phức tạp của mình. Không có kiểm thử đơn vị, tôi không biết làm thế nào để bắt đầu viết mã, vấn đề dường như quá lớn. Với thử nghiệm, tôi có thể bắt đầu với một phương pháp đơn giản và từng bước mở rộng nó với sự đảm bảo rằng các kịch bản đơn giản hơn vẫn sẽ hoạt động.

Tôi chắc chắn rằng việc sử dụng thử nghiệm đơn vị đã tiết kiệm cho tôi một vài ngày (hoặc vài tuần) mã hóa và ít nhiều đảm bảo tính chính xác của phương pháp của tôi.

Nếu sau này tôi nghĩ ra một kịch bản mới, tôi có thể thêm nó vào các thử nghiệm để xem nó có hoạt động hay không. Nếu không tôi có thể sửa đổi mã nhưng vẫn chắc chắn các kịch bản khác vẫn hoạt động chính xác. Điều này sẽ tiết kiệm ngày và ngày trong giai đoạn bảo trì và sửa lỗi.

Có, ngay cả mã được kiểm tra vẫn có thể có lỗi nếu người dùng thực hiện những việc bạn không nghĩ hoặc ngăn cản anh ta làm

Dưới đây chỉ là một số thử nghiệm tôi đã tạo để kiểm tra phương thức thanh toán của mình.

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);
    }
38
eroijen

Nếu chúng thực sự là tầm thường, thì đừng bận tâm thử nghiệm. Ví dụ, nếu chúng được thực hiện như thế này;

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

Mặt khác, nếu bạn đang làm một cái gì đó thông minh, (như mã hóa và giải mã mật khẩu trong getter/setter) thì hãy kiểm tra nó.

13
Steve Cooper

Quy tắc là bạn phải kiểm tra từng đoạn logic bạn viết. Nếu bạn thực hiện một số chức năng cụ thể trong getters và setters tôi nghĩ rằng chúng đáng để thử nghiệm. Nếu họ chỉ gán giá trị cho một số trường riêng, đừng bận tâm.

10
Slavo

Câu hỏi này dường như là một câu hỏi về nơi mà người ta vẽ đường thẳng về phương pháp nào được thử nghiệm và phương pháp nào không.

Các setters và getters để gán giá trị đã được tạo ra với sự nhất quán và tăng trưởng trong tương lai, và thấy trước rằng một lúc nào đó, người thiết lập/getter có thể phát triển thành các hoạt động phức tạp hơn. Sẽ có ý nghĩa khi đặt các bài kiểm tra đơn vị của các phương pháp đó, cũng vì mục đích nhất quán và tăng trưởng trong tương lai.

Độ tin cậy của mã, đặc biệt là trong khi trải qua thay đổi để thêm chức năng bổ sung, là mục tiêu chính. Tôi không biết có ai từng bị sa thải vì bao gồm cả setters/getters trong phương pháp thử nghiệm, nhưng tôi chắc chắn có những người muốn họ đã thử nghiệm các phương pháp mà họ biết hoặc có thể nhớ lại là các trình bao/lấy đơn giản nhưng không phải vậy trường hợp dài hơn.

Có thể một thành viên khác trong nhóm đã mở rộng các phương thức set/get để bao gồm logic hiện cần thử nghiệm nhưng sau đó không tạo ra các thử nghiệm. Nhưng bây giờ mã của bạn đang gọi các phương thức này và bạn không biết chúng đã thay đổi và cần thử nghiệm chuyên sâu, và thử nghiệm bạn thực hiện trong quá trình phát triển và QA không kích hoạt lỗi, nhưng dữ liệu kinh doanh thực sự vào ngày đầu tiên phát hành kích hoạt nó.

Bây giờ hai đồng đội sẽ tranh luận về việc ai đã làm rơi trái bóng và thất bại trong các bài kiểm tra đơn vị khi tập hợp/bị biến đổi để bao gồm logic có thể thất bại nhưng không được bao gồm trong bài kiểm tra đơn vị. Đồng đội ban đầu đã viết tập hợp/nhận sẽ có một thời gian dễ dàng hơn để làm sạch này nếu các bài kiểm tra được thực hiện từ ngày đầu tiên trên tập/đơn giản.

Ý kiến ​​của tôi là một vài phút "lãng phí" thời gian bao gồm TẤT CẢ các phương pháp với các bài kiểm tra đơn vị, thậm chí là tầm thường, có thể giúp tiết kiệm nhiều ngày đau đầu và mất tiền/danh tiếng của doanh nghiệp và mất việc của ai đó.

Và thực tế là bạn đã thực hiện các phương pháp tầm thường với các bài kiểm tra đơn vị có thể được nhìn thấy bởi người đồng đội cơ sở đó khi họ thay đổi các phương pháp tầm thường thành các phương pháp không tầm thường và Nhắc họ cập nhật bài kiểm tra, và bây giờ không có ai gặp rắc rối vì lỗi này được chứa từ đạt đến sản xuất.

Cách chúng tôi viết mã và kỷ luật có thể nhìn thấy từ mã của chúng tôi có thể giúp người khác.

6
Thomas Carlisle

Một câu trả lời kinh điển khác. Điều này, tôi tin, từ Ron Jeffries:

Chỉ kiểm tra mã mà bạn muốn làm việc.

4
user9397

Mã thực sự tầm thường như getters và setters không có hành vi bổ sung hơn là thiết lập một trường riêng là quá mức cần thiết để kiểm tra. Trong 3.0 C # thậm chí có một số đường cú pháp trong đó trình biên dịch sẽ chăm sóc trường riêng để bạn không phải lập trình điều đó.

Tôi thường viết rất nhiều bài kiểm tra rất đơn giản để xác minh hành vi mà tôi mong đợi từ các lớp học của mình. Ngay cả khi đó là những thứ đơn giản như thêm hai số. Tôi chuyển đổi rất nhiều giữa việc viết một bài kiểm tra đơn giản và viết một số dòng mã. Lý do cho điều này là sau đó tôi có thể thay đổi xung quanh mã mà không sợ tôi phá vỡ những điều tôi không nghĩ tới.

3
Mendelt

Bạn nên kiểm tra mọi thứ. Ngay bây giờ bạn có getters và setters, nhưng một ngày nào đó bạn có thể thay đổi chúng một chút, có thể để xác nhận hoặc một cái gì đó khác. Các bài kiểm tra bạn viết hôm nay sẽ được sử dụng vào ngày mai để đảm bảo mọi thứ vẫn hoạt động như bình thường. Khi bạn viết bài kiểm tra, bạn nên quên đi những cân nhắc như "ngay bây giờ nó tầm thường". Trong bối cảnh nhanh hoặc theo hướng kiểm tra, bạn nên kiểm tra giả định tái cấu trúc trong tương lai. Ngoài ra, bạn đã thử đưa vào các giá trị thực sự kỳ lạ như chuỗi cực dài hoặc nội dung "xấu" khác chưa? Chà, bạn không nên ... đừng bao giờ nghĩ rằng mã của bạn có thể bị lạm dụng tồi tệ như thế nào trong tương lai.

Nói chung tôi thấy rằng viết bài kiểm tra người dùng rộng rãi là ở một bên, mệt mỏi. Mặt khác, mặc dù nó luôn mang đến cho bạn cái nhìn sâu sắc vô giá về cách ứng dụng của bạn sẽ hoạt động và giúp bạn loại bỏ các giả định dễ dàng (và sai) (như: tên người dùng sẽ luôn có độ dài dưới 1000 ký tự).

3
Sklivvz

Đối với các mô-đun đơn giản có thể kết thúc trong bộ công cụ hoặc trong loại dự án nguồn mở, bạn nên kiểm tra càng nhiều càng tốt, bao gồm các getters và setters tầm thường. Điều bạn muốn ghi nhớ là việc tạo một bài kiểm tra đơn vị khi bạn viết một mô-đun cụ thể khá đơn giản và dễ hiểu. Thêm getters và setters là mã tối thiểu và có thể được xử lý mà không cần suy nghĩ nhiều. Tuy nhiên, khi mã của bạn được đặt trong một hệ thống lớn hơn, nỗ lực bổ sung này có thể bảo vệ bạn trước những thay đổi trong hệ thống cơ bản, chẳng hạn như thay đổi loại trong lớp cơ sở. Kiểm tra mọi thứ là cách tốt nhất để có hồi quy hoàn tất.

3
Dirigible

Kiểm tra mã soạn sẵn là một sự lãng phí thời gian, nhưng như Slavo nói, nếu bạn thêm một hiệu ứng phụ vào getters/setters của mình, thì bạn nên viết một bài kiểm tra để đi kèm với chức năng đó.

Nếu bạn đang thực hiện phát triển dựa trên thử nghiệm, trước tiên bạn nên viết hợp đồng (ví dụ: giao diện), sau đó viết (các) thử nghiệm để thực hiện giao diện đó ghi lại kết quả/hành vi dự kiến. Sau đó tự viết phương thức của bạn, mà không cần chạm vào mã trong các bài kiểm tra đơn vị của bạn. Cuối cùng, lấy một công cụ bao phủ mã và đảm bảo các bài kiểm tra của bạn thực hiện tất cả các đường dẫn logic trong mã của bạn.

3
warren_s

nói chung, khi một phương thức chỉ được xác định cho các giá trị nhất định, hãy kiểm tra các giá trị trên và hơn đường viền của những gì được chấp nhận. Nói cách khác, đảm bảo phương thức của bạn thực hiện những gì nó phải làm, nhưng không có gì nữa . Điều này rất quan trọng, bởi vì khi bạn sắp thất bại, bạn muốn thất bại sớm.

Trong hệ thống phân cấp thừa kế, hãy đảm bảo kiểm tra LSP tuân thủ.

Kiểm tra getters và setters mặc định dường như không hữu ích cho tôi, trừ khi bạn dự định thực hiện một số xác nhận sau này.

2
Rik

tốt nếu bạn nghĩ rằng nó có thể phá vỡ, viết một bài kiểm tra cho nó. Tôi thường không kiểm tra setter/getter, nhưng giả sử bạn tạo một cái cho User.Name, nối tên và họ, tôi sẽ viết một bài kiểm tra để nếu ai đó thay đổi thứ tự cho họ và tên, ít nhất anh ta sẽ biết ông đã thay đổi một cái gì đó đã được thử nghiệm.

2
pmlarocque

Câu trả lời kinh điển là "kiểm tra bất cứ điều gì có thể phá vỡ." Nếu bạn chắc chắn các thuộc tính sẽ không bị hỏng, đừng kiểm tra chúng.

Và một khi một cái gì đó được tìm thấy đã bị hỏng (bạn tìm thấy một lỗi), rõ ràng nó có nghĩa là bạn cần phải kiểm tra nó. Viết một bài kiểm tra để tái tạo lỗi, xem nó thất bại, sau đó sửa lỗi, sau đó xem vượt qua bài kiểm tra.

2
Eric Normand

Sẽ không hại khi viết bài kiểm tra đơn vị cho getters và setters của bạn. Ngay bây giờ, họ có thể đang thực hiện các bộ/trường dưới mui xe, nhưng trong tương lai bạn có thể có logic xác thực hoặc các phụ thuộc giữa các thuộc tính cần được kiểm tra. Viết nó bây giờ dễ dàng hơn trong khi bạn đang nghĩ về nó sau đó ghi nhớ trang bị thêm nếu thời điểm đó đến.

2
Bob King

Lý tưởng nhất là bạn đã thực hiện bài kiểm tra đơn vị của bạn khi bạn đang viết lớp. Đây là cách bạn muốn làm điều đó khi sử dụng Phát triển hướng thử nghiệm. Bạn thêm các bài kiểm tra khi bạn triển khai từng điểm chức năng, đảm bảo rằng bạn cũng bao quát các trường hợp Edge với bài kiểm tra.

Viết các bài kiểm tra sau đó là đau đớn hơn nhiều, nhưng có thể làm được.

Đây là những gì tôi sẽ làm ở vị trí của bạn:

  1. Viết một bộ kiểm tra cơ bản kiểm tra chức năng cốt lõi.
  2. Nhận NCover và chạy nó trong bài kiểm tra của bạn. Phạm vi kiểm tra của bạn có thể sẽ được khoảng 50% tại thời điểm này.
  3. Tiếp tục thêm các bài kiểm tra bao gồm các trường hợp Edge của bạn cho đến khi bạn nhận được bảo hiểm khoảng 80% -90%

Điều này sẽ cung cấp cho bạn một bộ các bài kiểm tra đơn vị hoạt động tốt sẽ hoạt động như một bộ đệm tốt chống lại hồi quy.

Vấn đề duy nhất với cách tiếp cận này là mã phải được được thiết kế để có thể kiểm tra theo cách này. Nếu bạn thực hiện bất kỳ lỗi ghép nối nào từ sớm, bạn sẽ không thể có được phạm vi bảo hiểm cao một cách dễ dàng.

Đây là lý do tại sao nó thực sự quan trọng để viết các bài kiểm tra trước khi bạn viết mã. Nó buộc bạn phải viết mã được ghép lỏng lẻo.

1
Simon Johnson

Nó làm cho mã của chúng tôi tốt hơn ... thời gian!

Một điều mà chúng tôi các nhà phát triển phần mềm quên mất khi thực hiện phát triển theo hướng kiểm tra là mục đích đằng sau các hành động của chúng tôi. Nếu một bài kiểm tra đơn vị đang được viết sau khi đã có mã sản xuất, giá trị của bài kiểm tra sẽ giảm xuống (nhưng không bị mất hoàn toàn).

Theo tinh thần thực sự cho thử nghiệm đơn vị, các thử nghiệm này không phải chủ yếu ở đó để "kiểm tra" thêm mã của chúng tôi; hoặc để có được phạm vi bảo hiểm mã tốt hơn 90% -100%. Đây là tất cả lợi ích bên lề của việc viết bài kiểm tra trước. Phần thưởng lớn là mã kết thúc sản xuất của chúng tôi được viết tốt hơn nhiều do quy trình tự nhiên của TDD.

Để giúp truyền đạt tốt hơn ý tưởng này, những điều sau đây có thể hữu ích trong việc đọc:

Lý thuyết thiếu sót của các bài kiểm tra đơn vị
[.__.] Phát triển phần mềm có mục đích

Nếu chúng tôi cảm thấy rằng hành động viết nhiều bài kiểm tra đơn vị hơn là điều giúp chúng tôi có được một sản phẩm chất lượng cao hơn, thì chúng tôi có thể bị Vận chuyển hàng hóa của Phát triển hướng thử nghiệm.

1
Scott Saad

Đừng kiểm tra mã rõ ràng đang hoạt động. Vì vậy, nếu setters và getters của bạn chỉ là "propertyvalue = value" và "return propertyvalue" thì sẽ không có ý nghĩa gì khi kiểm tra nó.

1
erlando

Ngay cả get/set cũng có thể có những hậu quả kỳ lạ, tùy thuộc vào cách chúng được thực hiện, vì vậy chúng nên được coi là phương thức.

Mỗi thử nghiệm trong số này sẽ cần chỉ định các bộ tham số cho các thuộc tính, xác định cả hai thuộc tính có thể chấp nhận và không được chấp nhận để đảm bảo trả lại/thất bại cuộc gọi theo cách mong đợi.

Bạn cũng cần lưu ý về vấn đề bảo mật, như một ví dụ SQL và kiểm tra những thứ này.

Vì vậy, có, bạn cần phải lo lắng về việc kiểm tra các thuộc tính.

1
CestLaGalere

Tôi tin rằng thật ngớ ngẩn khi kiểm tra getters & setters khi họ chỉ thực hiện một thao tác đơn giản. Cá nhân tôi không viết các bài kiểm tra đơn vị phức tạp để bao gồm bất kỳ mẫu sử dụng nào. Tôi cố gắng viết đủ các bài kiểm tra để đảm bảo tôi đã xử lý hành vi thực thi bình thường và nhiều trường hợp lỗi tôi có thể nghĩ ra. Tôi sẽ viết thêm các bài kiểm tra đơn vị như là một phản ứng với các báo cáo lỗi. Tôi sử dụng thử nghiệm đơn vị để đảm bảo mã đáp ứng các yêu cầu và để sửa đổi trong tương lai dễ dàng hơn. Tôi cảm thấy sẵn sàng hơn để thay đổi mã khi tôi biết rằng nếu tôi phá vỡ một cái gì đó, một bài kiểm tra sẽ thất bại.

1
Andrei Savu

Mặc dù có thể đoán chính xác nơi mã của bạn cần kiểm tra, nhưng tôi thường nghĩ rằng bạn cần số liệu để sao lưu dự đoán này. Kiểm tra đơn vị theo quan điểm của tôi đi đôi với các số liệu bảo hiểm mã.

Mã với rất nhiều bài kiểm tra nhưng phạm vi bảo hiểm nhỏ chưa được kiểm tra tốt. Điều đó nói rằng, mã với phạm vi bảo hiểm 100% nhưng không kiểm tra các trường hợp ràng buộc và lỗi cũng không tuyệt vời.

Bạn muốn cân bằng giữa độ bao phủ cao (tối thiểu 90%) và dữ liệu đầu vào biến đổi.

Hãy nhớ kiểm tra "rác trong"!

Ngoài ra, kiểm tra đơn vị không phải là kiểm tra đơn vị trừ khi kiểm tra lỗi. Các bài kiểm tra đơn vị không có xác nhận hoặc được đánh dấu bằng các ngoại lệ đã biết sẽ chỉ kiểm tra xem mã không chết khi chạy!

Bạn cần thiết kế các bài kiểm tra của mình để chúng luôn báo cáo các lỗi hoặc dữ liệu không mong muốn/không mong muốn!

1
Ray Hayes

Tôi sẽ viết một bài kiểm tra cho bất cứ điều gì bạn đang viết mã cho điều đó có thể kiểm tra được bên ngoài giao diện GUI.

Thông thường, bất kỳ logic nào tôi viết có bất kỳ logic nghiệp vụ nào tôi đặt bên trong lớp logic hoặc lớp nghiệp vụ khác.

Sau đó viết bài kiểm tra cho bất cứ điều gì làm một cái gì đó là dễ dàng để làm.

Trước hết, hãy viết một bài kiểm tra đơn vị cho từng phương thức công khai trong "Lớp logic nghiệp vụ" của bạn.

Nếu tôi có một lớp học như thế này:

   public class AccountService
    {
        public void DebitAccount(int accountNumber, double amount)
        {

        }

        public void CreditAccount(int accountNumber, double amount)
        {

        }

        public void CloseAccount(int accountNumber)
        {

        }
    }

Điều đầu tiên tôi sẽ làm trước khi tôi viết bất kỳ mã nào biết rằng tôi có những hành động này để thực hiện sẽ là bắt đầu viết các bài kiểm tra đơn vị.

   [TestFixture]
    public class AccountServiceTests
    {
        [Test]
        public void DebitAccountTest()
        {

        }

        [Test]
        public void CreditAccountTest()
        {

        }

        [Test]
        public void CloseAccountTest()
        {

        }
    }

Viết bài kiểm tra của bạn để xác thực mã bạn đã viết để làm một cái gì đó. Nếu bạn lặp đi lặp lại một bộ sưu tập các thứ và thay đổi một cái gì đó về mỗi thứ đó, hãy viết một bài kiểm tra thực hiện điều tương tự và Khẳng định điều đó thực sự đã xảy ra.

Có rất nhiều cách tiếp cận khác mà bạn có thể thực hiện, cụ thể là Behavoir Driven Development (BDD), có liên quan nhiều hơn và không phải là nơi tuyệt vời để bắt đầu với các kỹ năng kiểm tra đơn vị của bạn.

Vì vậy, đạo đức của câu chuyện là, kiểm tra bất cứ điều gì làm bất cứ điều gì bạn có thể lo lắng, giữ cho bài kiểm tra đơn vị kiểm tra những thứ cụ thể có kích thước nhỏ, rất nhiều bài kiểm tra là tốt.

Giữ logic kinh doanh của bạn bên ngoài lớp Giao diện người dùng để bạn có thể dễ dàng viết bài kiểm tra cho họ và bạn sẽ ổn.

Tôi khuyên bạn nên TestDriven.Net hoặc ReSharper vì cả hai đều dễ dàng tích hợp vào Visual Studio.

1
Dean Poulin

Theo tôi hiểu các bài kiểm tra đơn vị trong bối cảnh phát triển nhanh, Mike, vâng, bạn cần kiểm tra các getters và setters (giả sử chúng được hiển thị công khai). Toàn bộ khái niệm kiểm thử đơn vị là kiểm tra đơn vị phần mềm, là một lớp trong trường hợp này, dưới dạng hộp đen . Vì các getters và setters có thể nhìn thấy bên ngoài, bạn cần kiểm tra chúng cùng với Xác thực và Lưu.

1
Onorio Catenacci

Nếu phương thức Xác thực và Lưu sử dụng các thuộc tính, thì các thử nghiệm của bạn sẽ gián tiếp chạm vào các thuộc tính. Miễn là các thuộc tính chỉ cung cấp quyền truy cập vào dữ liệu, thì không cần thiết phải kiểm tra rõ ràng (trừ khi bạn sẽ bảo hiểm 100%).

1
Tom Walker

Tôi sẽ kiểm tra getters và setters của bạn. Tùy thuộc vào người viết mã, một số người thay đổi ý nghĩa của các phương thức getter/setter. Tôi đã thấy khởi tạo biến và xác nhận khác là một phần của phương thức getter. Để kiểm tra loại điều này, bạn muốn kiểm tra đơn vị bao gồm mã đó một cách rõ ràng.

1
Peter Bernier

Cá nhân tôi sẽ "kiểm tra bất cứ thứ gì có thể phá vỡ" và getter đơn giản (hoặc thậm chí các thuộc tính tự động tốt hơn) sẽ không bị hỏng. Tôi chưa bao giờ có một tuyên bố trở lại đơn giản thất bại và do đó không bao giờ có thử nghiệm cho họ. Nếu các getters có tính toán trong chúng hoặc một số dạng câu lệnh khác, tôi chắc chắn sẽ thêm các bài kiểm tra cho chúng.

Cá nhân tôi sử dụng Moq làm khung đối tượng giả và sau đó xác minh rằng đối tượng của tôi gọi các đối tượng xung quanh theo cách cần thiết.

1
tronda

Bạn phải bao gồm việc thực hiện mọi phương thức của lớp bằng UT và kiểm tra giá trị trả về của phương thức. Điều này bao gồm getters và setters, đặc biệt trong trường hợp các thành viên (thuộc tính) là các lớp phức tạp, đòi hỏi phân bổ bộ nhớ lớn trong quá trình khởi tạo của chúng. Gọi setter với một số chuỗi rất lớn chẳng hạn (hoặc một cái gì đó có ký hiệu Hy Lạp) và kiểm tra kết quả là chính xác (không bị cắt cụt, mã hóa là tốt, v.v.)

Trong trường hợp số nguyên đơn giản cũng được áp dụng - điều gì xảy ra nếu bạn vượt qua lâu thay vì số nguyên? Đó là lý do bạn viết UT cho :)

1
m_pGladiator

Kiểm tra một lớp nên xác minh rằng:

  1. phương thức và thuộc tính trả về giá trị mong đợi
  2. Các ngoại lệ phù hợp được đưa ra khi một đối số không hợp lệ được cung cấp
  3. Tương tác giữa lớp và các đối tượng khác xảy ra như mong đợi khi một phương thức đã cho được gọi

Tất nhiên, nếu các getters và setters không có logic đặc biệt thì các bài kiểm tra của các phương thức xác thực và lưu sẽ bao gồm chúng, nhưng nếu không thì nên viết một bài kiểm tra khám phá

1
Crippledsmurf

Tôi sẽ khuyên bạn nên viết nhiều bài kiểm tra cho các phương thức Xác thực và Lưu của bạn. Ngoài trường hợp thành công (nơi cung cấp tất cả các tham số, mọi thứ đều được viết đúng chính tả, v.v.), tốt nhất là nên kiểm tra các trường hợp lỗi khác nhau (tham số không chính xác hoặc thiếu, kết nối cơ sở dữ liệu không khả dụng nếu có, v.v.). Tôi khuyên bạn nên Kiểm tra đơn vị thực dụng trong C # với NUnit làm tài liệu tham khảo.

Như những người khác đã nêu, các bài kiểm tra đơn vị cho getters và setters là quá mức cần thiết, trừ khi có logic có điều kiện trong getters và setters của bạn.

1
Scott Lawrence

Tôi sẽ không kiểm tra các thiết lập thực tế của tài sản. Tôi sẽ quan tâm nhiều hơn về cách những tài sản đó được người tiêu dùng yêu thích và những gì họ đưa vào. Với bất kỳ thử nghiệm nào, bạn phải cân nhắc rủi ro với thời gian/chi phí thử nghiệm.

1
Bloodhound

Bạn nên kiểm tra "mọi khối mã không tầm thường" bằng cách sử dụng các bài kiểm tra đơn vị càng nhiều càng tốt.

Nếu các thuộc tính của bạn là tầm thường và không chắc ai đó sẽ đưa ra một lỗi trong đó, thì nó sẽ an toàn để không kiểm tra đơn vị chúng.

Các phương thức Xác thực () và Lưu () của bạn trông giống như các ứng cử viên tốt để thử nghiệm.

1
user7015

Viết mã không có giá trị luôn là một ý tưởng tồi. Vì thử nghiệm đề xuất không thêm giá trị cho dự án của bạn (hoặc rất gần với nó). Sau đó, bạn đang lãng phí thời gian quý báu mà bạn có thể dành để viết mã thực sự mang lại giá trị.

0
pjesi

Tôi thứ hai kiểm tra bất cứ điều gì có thể phá vỡkhông viết các bài kiểm tra ngớ ngẩn. Nhưng nguyên lý quan trọng nhất là kiểm tra bất cứ thứ gì bạn tìm thấy đều bị hỏng: nếu một phương thức nào đó hành xử kỳ quặc hãy viết một bài kiểm tra để phác thảo tập dữ liệu khiến nó bị lỗi, sau đó sửa lỗi và xem thanh màu xanh lá cây. Đồng thời kiểm tra các giá trị dữ liệu "ranh giới" (null, 0, MAX_INT, danh sách trống, bất cứ điều gì).

0
Manrico Corazzi

Khi viết bài kiểm tra đơn vị, hoặc thực sự là bất kỳ bài kiểm tra nào, bạn xác định những gì cần kiểm tra bằng cách xem xét các điều kiện biên của những gì bạn đang kiểm tra. Ví dụ: bạn có một hàm gọi là is_prime. May mắn thay, nó thực hiện đúng như tên gọi của nó và cho bạn biết đối tượng số nguyên có phải là số nguyên tố hay không. Đối với điều này, tôi giả sử bạn đang sử dụng các đối tượng. Bây giờ, chúng ta sẽ cần kiểm tra xem các kết quả hợp lệ đã xảy ra đối với một phạm vi các đối tượng nguyên tố và không nguyên tố đã biết. Đó là điểm khởi đầu của bạn.

Về cơ bản, hãy xem điều gì sẽ xảy ra với một hàm, phương thức, chương trình hoặc tập lệnh, và sau đó ở những gì chắc chắn không xảy ra với cùng một mã. Đó là cơ sở cho bài kiểm tra của bạn. Chỉ cần chuẩn bị để sửa đổi các bài kiểm tra của bạn khi bạn trở nên hiểu biết hơn về những gì nên sẽ xảy ra với mã của bạn.

0
Dan

Nguyên tắc tốt nhất tôi từng thấy là kiểm tra mọi thứ mà bạn không thể biết trong nháy mắt, chắc chắn, sẽ hoạt động tốt. Bất cứ điều gì nhiều hơn và bạn kết thúc việc kiểm tra ngôn ngữ/môi trường.

0
user74754