Tiêu chuẩn kiểm tra đơn vị


22

Thông thường khi nói về các tiêu chuẩn mã hóa, chúng ta đề cập đến mã của chính chương trình, nhưng còn các bài kiểm tra đơn vị thì sao? Có hướng dẫn tiêu chuẩn mã hóa nào đó là duy nhất cho các bài kiểm tra đơn vị không? Họ là ai?

Câu trả lời:


12

Ngoài đỉnh đầu, tôi có thể nghĩ ra ba điểm khác biệt trong phong cách mã hóa cho mã kiểm tra.

Trong phương pháp kiểm tra đặt tên, tôi theo mô hình của shouldDoSomethingWhenSomeConditionHolds.

Trong thử nghiệm, thông thường tuân theo mẫu khoảng cách sau:

@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
    // Some lines 
    // of setup code
    // go here.

    // The action being tested happens after a blank line.

    // An assertion follows another blank line.
}

Một số nhấn mạnh chỉ một khẳng định cho mỗi bài kiểm tra, nhưng điều này là xa phổ quát.

DRY (Đừng lặp lại chính mình) ít được xem xét trong mã kiểm tra hơn trong mã sản xuất. Mặc dù một số mã lặp lại nên được đặt trong phương thức setUp hoặc lớp testUtils, việc phấn đấu không lặp lại trong mã kiểm tra sẽ dẫn đến các thử nghiệm không khớp và không linh hoạt, điều này không khuyến khích tái cấu trúc.


Tất nhiên, có một loạt các mẫu, đó là lý do tại sao bạn cũng nên cung cấp một câu trả lời.
Eric Wilson

10
Đó là mô hình Arrange, Act, Assert .
StuperUser

DRY vẫn quan trọng. Nếu bạn cần thực hiện cùng một xác nhận trong nhiều thử nghiệm, hãy tạo chức năng chung và gọi nó trong tất cả các thử nghiệm.
MiFreidgeim SO-ngừng trở thành ác quỷ

@MichaelFreidgeim Có thể chúng ta chỉ nói về độ, nhưng tôi có dung sai cao hơn đáng kể cho sự lặp lại trong mã kiểm tra. Tôi đã có một vài kinh nghiệm trong việc xây dựng các bộ thử nghiệm với rất ít sự lặp lại và thấy rằng các thử nghiệm trở nên khó sửa đổi và hiểu khi các yêu cầu thay đổi. Sau đó, tôi đã ngừng lo lắng về DRY trong các thử nghiệm và các bộ thử nghiệm của tôi đã dễ sử dụng hơn. <nhún>
Eric Wilson

16

Roy Osherove đề xuất mẫu sau để đặt tên cho các bài kiểm tra của bạn:

NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior() 

Xem http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStiterias.aspx


Tôi đồng ý với Roy. Nó cải thiện khả năng đọc, mặc dù ReSharper vẫn nói với tôi rằng tôi nên xóa chúng đi NameOfMethodUnderTestStateUnderTestExpectedBehavior();)
Oscar Mederos

Làm thế nào để làm cho công việc này khi phương thức bị quá tải, vì vậy có thể có nhiều phương thức có cùng tên?
Narendra Pathai

6

Điều chính là phải nhớ rằng các bài kiểm tra đơn vị về cơ bản là các thông số kỹ thuật nhỏ. Điều này có nghĩa là sự nhấn mạnh phải luôn luôn dễ đọc.

Thứ nhất, điều này có nghĩa là tên phải truyền đạt rõ ràng những gì đang được thử nghiệm và những gì đang được khẳng định.

Thứ hai, mặc dù đôi khi bị lãng quên, đó là thông số kỹ thuật mà họ nên làm như vậy - chỉ định hành vi. Đó là, các bài kiểm tra đơn vị không nên chứa logic - hoặc có khả năng chúng rơi vào bẫy lặp lại chức năng của chương trình thay vì kiểm tra nó.

Đôi khi các bài kiểm tra sẽ liên quan đến các đối tượng phức tạp để thiết lập, bạn nên cố gắng tách logic thiết lập này khỏi các thử nghiệm của mình bằng cách sử dụng một cái gì đó như mẹ đối tượng hoặc trình tạo dữ liệu thử nghiệm .

Tôi sẽ làm tròn với một vài khuyến nghị cuốn sách:

Các mẫu thử nghiệm xUnit: Tái cấu trúc Mã kiểm tra: Cuốn sách tuyệt vời, một số người cho rằng nó hơi khô khan nhưng tôi không nghĩ vậy. Đi vào rất nhiều chi tiết về rất nhiều cách tổ chức kiểm tra khác nhau và làm thế nào để duy trì chúng. Có liên quan nếu bạn đang sử dụng một cái gì đó như NUnit, vv

Nghệ thuật kiểm tra đơn vị: Với các ví dụ trong .Net : Cuốn sách hay nhất về sự khéo léo của việc viết và duy trì các bài kiểm tra. Mặc dù thực sự mới nhưng tôi thấy các phần chế giễu đã có một chút ngày vì cú pháp AAA bây giờ khá chuẩn chứ không phải là một cách khác để làm điều đó.

Phát triển phần mềm hướng đối tượng, được hướng dẫn bởi các bài kiểm tra : Cuốn sách này thật tuyệt vời! Cho đến nay, cuốn sách thử nghiệm đơn vị tốt nhất và là cuốn sách tiên tiến duy nhất đưa thử nghiệm đơn vị là công dân hạng nhất trong quá trình thiết kế. Đã đọc nó khi nó là một phiên bản beta công khai và được giới thiệu kể từ đó. Ví dụ làm việc thực tế tuyệt vời được sử dụng trong suốt cuốn sách. Mặc dù vậy, tôi khuyên bạn nên đọc cuốn sách của Roy.


IMHO không có vấn đề gì đối với các bài kiểm tra đơn vị có chứa logic: Hoàn toàn hợp lý để kiểm tra phiên bản thuật toán hiệu quả, được tối ưu hóa cao bằng cách sử dụng thuật toán ngây thơ thực hiện điều tương tự để xác định hành vi chính xác. Ví dụ, hãy tưởng tượng thử nghiệm bảng băm bằng cách xây dựng một mảng kết hợp dựa trên tìm kiếm tuyến tính.
dsimcha

2
Có, nhưng điều đó nằm ngoài thử nghiệm trong các trình xây dựng dữ liệu thử nghiệm (bản thân chúng phải là đơn vị được kiểm tra nếu logic bên trong chúng không tầm thường). Ngoại lệ cho điều này sẽ là các thư viện bên thứ 3 thường "đáng tin cậy" là chính xác và có thể được sử dụng mà không cần kiểm tra.
FinnNk

3

Đừng đặt logic trong các bài kiểm tra đơn vị của bạn. Ví dụ: giả sử bạn đang thử nghiệm một phương thức thêm, bạn có thể có một cái gì đó như thế này:

void MyTest_SaysHello()
{
   string name = "Bob";
   string expected = string.Format("Hello, {0}", name);
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello(name);
   Assert.AreEqual(expected, actual);
}

Trong trường hợp cụ thể này, bạn có thể lặp lại logic tương tự như trong bài kiểm tra, vì vậy về cơ bản, bạn đang kiểm tra "1 + 1 == 1 + 1", thay vì "1 + 1 == 2", đó là Thử nghiệm "thực sự". Vì vậy, những gì bạn thực sự muốn mã kiểm tra của bạn trông giống như:

void MyTest_SaysHello()
{
   string expected = "Hello, Bob";
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello("Bob");
   Assert.AreEqual(expected, actual);
}

2
Hiệu chỉnh nhỏ: Tôi nghĩ bạn có nghĩa là 'chuỗi dự kiến ​​= chuỗi.Format ("Xin chào, Bob")' nên là 'chuỗi mong đợi = "Xin chào, Bob"'.
Mike Rosenblum

@MikeRosenblum bạn rõ ràng đúng và ai đó đã cố gắng sửa nó, nhưng hai nhà phê bình đã từ chối chỉnh sửa này
Konrad Morawski

@Konrad: thật lạ. Đây là một diễn đàn lập trình, phải không?
Mike Rosenblum

Tôi đã chỉnh sửa câu trả lời một lần nữa theo đề nghị của Mike Rosenblum.
bdsl

0

Tên phương thức mô tả dài. Hãy nhớ rằng, các phương thức kiểm tra không bao giờ được gọi từ mã (chúng được gọi bởi trình chạy thử nghiệm đơn vị phát hiện và gọi chúng thông qua phản xạ), do đó, thật điên rồ và có tên phương thức dài 50-80 ký tự. Quy ước đặt tên cụ thể (trường hợp lạc đà, dấu gạch dưới, "nên", "phải", "khi", "đã cho", v.v.) không thực sự quan trọng miễn là tên trả lời ba câu hỏi:

  • những gì đang được thử nghiệm?
  • những điều kiện là gì?
  • kết quả được mong đợi là gì?

Phương pháp kiểm tra nên ngắn gọn .

Phương pháp thử nên có cấu trúc đơn giản, tuyến tính . Không có hoặc cấu trúc vòng lặp.

Các phương pháp thử nghiệm phải tuân theo mẫu "sắp xếp hành động-khẳng định" .

Mỗi bài kiểm tra nên kiểm tra một điều . Điều này thường có nghĩa là một khẳng định cho mỗi bài kiểm tra. Một bài kiểm tra như thế { Do A; Assert B; Assert C; }nên được tái cấu trúc thành hai: { Do A; Assert B; }{ Do A; Assert C; }

Tránh dữ liệu ngẫu nhiên hoặc những thứ như 'DateTime.Now'

Đảm bảo rằng tất cả các thành viên bộ ghép đo được trả lại tình trạng ban đầu của họ vào cuối của bài kiểm tra (ví dụ như sử dụng một teardown )

Ngay cả khi bạn loại bỏ trùng lặp một cách tàn nhẫn trong mã sản xuất của mình, sao chép mã trong đồ đạc thử nghiệm là mối quan tâm nhỏ hơn nhiều.


-1

Tương tự như những gì Farmboy đã đề cập, định dạng tên phương thức của tôi

 <MethodName>Should<actionPerformed>When<Condition>

ví dụ

 GetBalanceShouldReturnAccountBalance() {
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.