a

Câu hỏi Kiểm tra đơn vị Danh mục chống mẫu


chống mẫu : phải có ít nhất hai yếu tố chính hiện diện để phân biệt chính thức một mẫu chống thực tế từ thói quen xấu đơn giản, hành vi xấu hoặc ý tưởng tồi:

  • Một số mô hình hành động, quá trình hoặc cấu trúc lặp đi lặp lại ban đầu dường như có lợi, nhưng cuối cùng tạo ra nhiều hậu quả xấu hơn kết quả có lợi, và
  • Một giải pháp tái cấu trúc được ghi chép rõ ràng, được chứng minh trong thực tế thực tế và có thể lặp lại.

Bỏ phiếu cho mẫu chống TDD mà bạn đã thấy "trong tự nhiên" một lần quá nhiều.
Bài đăng trên blog của James Carr và Thảo luận liên quan về yahoogroup thử nghiệm phát triển

Nếu bạn đã tìm thấy một 'không tên' một .. đăng 'em quá. Một bài cho mỗi anti-pattern xin vui lòng để làm cho số phiếu bầu cho một cái gì đó.

Sở thích của tôi là tìm ra tập hợp con hàng đầu để tôi có thể thảo luận về họ trong một bữa ăn trưa gặp nhau trong tương lai gần.


203


gốc


Aaron, bạn dường như là tất cả trên này :) Nó sẽ là một ý tưởng tốt để thêm các tag-line hoặc khẩu hiệu như ý kiến ​​để chúng tôi có thể có ít di chuyển .. những gì nói? - Gishu
Điều này đang đến khá tốt .. cảm ơn guys n gals. Giữ họ đến .. một trong những bài viết SO thông tin nhất IMHO - Gishu
+1 yêu chủ đề này !!! Và hầu hết trong số này là rất đúng và chiếm ưu thế quá! - Chii
Nice thread, tại sao là cộng đồng wiki này mặc dù ??? - Quibblesome
Coz nó là loại của một cuộc thăm dò ý kiến ​​- bạn sẽ không muốn thu hoạch đại diện chỉ coz bạn đăng các loại phổ biến nhất của anti-pattern;) - Gishu


Các câu trả lời:


Những công dân hạng hai - Mã thử nghiệm không được tái cấu trúc tốt như mã sản xuất, có chứa nhiều mã trùng lặp, khiến cho việc kiểm tra trở nên khó khăn.


70





The Ride miễn phí / Piggyback - James Carr, Tim Ottinger
Thay vì viết một phương pháp thử nghiệm mới để kiểm tra khác / tính năng / chức năng riêng biệt, một xác nhận mới (và các hành động tương ứng của nó tức là các bước hành động từ AAA) đi cùng trong một trường hợp thử nghiệm hiện có.


67



Vâng, đó là cái tôi thích nhất. Tôi làm nó suốt. Oh ... chờ đã ... bạn nói rằng đây là một xấu Điều. :-) - guidoism
Tôi không chắc chắn đây là một mô hình chống. Tất cả các bất biến phải là true sau mỗi cuộc gọi mutator có thể. Vì vậy, bạn sẽ muốn kiểm tra xem mọi bất biến là true sau mỗi kết hợp của mutator và dữ liệu đầu vào mà bạn đang thử nghiệm. Nhưng bạn sẽ muốn giảm trùng lặp và đảm bảo bạn kiểm tra tất cả các các bất biến, bao gồm cả những bất biến hiện tại gây ra lỗi kiểm tra. Vì vậy, bạn đặt tất cả trong một checkInvariants() chức năng xác minh và sử dụng nó trong mọi thử nghiệm. Các thay đổi mã và một biến thể khác được thêm vào. Bạn cũng đặt nó vào hàm này. Nhưng nó là một freerider. - Raedwald
@ Raedwald - Theo thời gian, tên thử nghiệm không còn khớp với tất cả những thứ mà nó kiểm tra. Ngoài ra bạn có một số thrashing do intertwining kiểm tra; một thất bại không chỉ ra nguyên nhân chính xác của thất bại. ví dụ. một ví dụ kinh điển của thử nghiệm này sẽ đọc một cái gì đó như Opaque Superset của tất cả các bước sắp xếp >> Đạo luật >> Assert A >> Hành động một số chi tiết >> Assert B >> Hành động một số chi tiết >> khẳng định C. Bây giờ lý tưởng nếu A và C bị hỏng , bạn sẽ thấy 2 lỗi kiểm tra. Với bài kiểm tra ở trên, bạn sẽ chỉ thấy một bài kiểm tra, sau đó bạn sửa A và trong lần chạy tiếp theo, nó sẽ cho bạn biết rằng bây giờ C đã bị hỏng. bây giờ hãy tưởng tượng 5-6 bài kiểm tra riêng biệt hợp nhất với nhau .. - Gishu
"tên thử nghiệm không còn khớp với tất cả những thứ mà nó kiểm tra" Chỉ khi thử nghiệm được đặt tên cho điều kiện bài viết ban đầu có mặt. Nếu bạn đặt tên cho sự kết hợp của tên phương thức, trạng thái thiết lập và dữ liệu đầu vào (đối số phương thức), thì không có vấn đề gì. - Raedwald
"một thất bại không chỉ ra nguyên nhân chính xác của thất bại" không quả quyết thất bại bao giờ cho biết nguyên nhân của một thất bại. Điều đó đòi hỏi một số delving vào các chi tiết thực hiện: gỡ lỗi cho một thất bại hồi quy, kiến ​​thức của bạn về tình trạng phát triển cho một số công việc TDD. - Raedwald


Đường dẫn hạnh phúc

Bài kiểm tra nằm trên đường dẫn hạnh phúc (tức là kết quả mong đợi) mà không cần kiểm tra ranh giới và ngoại lệ.

JUnit Antipatterns


64



Nguyên nhân: Hoặc là hạn chế thời gian phóng đại hoặc lười biếng trắng trợn. Giải pháp tái cấu trúc: Dành chút thời gian để viết nhiều bài kiểm tra hơn để loại bỏ các mặt tích cực sai. Nguyên nhân thứ hai cần có roi da. :) - Spoike


Anh hùng địa phương

Một trường hợp thử nghiệm phụ thuộc vào một cái gì đó cụ thể cho môi trường phát triển mà nó đã được viết để chạy. Kết quả là bài kiểm tra chuyển vào các hộp phát triển, nhưng không thành công khi ai đó cố gắng chạy nó ở nơi khác.

Ẩn phụ thuộc

Liên quan chặt chẽ với người anh hùng địa phương, một bài kiểm tra đơn vị yêu cầu một số dữ liệu hiện có đã được phổ biến ở đâu đó trước khi chạy thử nghiệm. Nếu dữ liệu đó không được điền, thử nghiệm sẽ không thành công và để lại ít dấu hiệu cho nhà phát triển những gì họ muốn hoặc tại sao ... buộc họ phải đào sâu qua mẫu mã để tìm ra dữ liệu mà nó đang sử dụng được cho là bắt nguồn từ đâu.


Thật đáng buồn khi thấy điều này quá nhiều lần với các tập tin .dll cổ đại và phụ thuộc vào các tập tin .ini liên tục và không đồng bộ trên bất kỳ hệ thống sản xuất cụ thể nào, hãy để một mình trên máy của bạn mà không cần tham vấn rộng rãi với ba nhà phát triển chịu trách nhiệm về những dll đó. Thở dài.


59



Đó là một ví dụ hay về từ viết tắt của nhà phát triển WOMPC. "Hoạt động trên PC của tôi!" (thường được nói để có được người kiểm tra ra khỏi lưng của bạn.) - Joris Timmermans


Chain Gang

Một vài thử nghiệm phải chạy theo một thứ tự nhất định, nghĩa là một thử nghiệm thay đổi trạng thái toàn cục của hệ thống (các biến toàn cục, dữ liệu trong cơ sở dữ liệu) và (các) thử nghiệm tiếp theo phụ thuộc vào nó.

Bạn thường thấy điều này trong các bài kiểm tra cơ sở dữ liệu. Thay vì quay trở lại teardown(), các thử nghiệm cam kết các thay đổi của chúng đối với cơ sở dữ liệu. Một nguyên nhân phổ biến khác là các thay đổi đối với trạng thái toàn cục không được bao bọc trong các khối thử / cuối cùng sẽ làm sạch nếu thử nghiệm thất bại.


58



điều này chỉ là đồng bằng khó chịu .. Breaks các bài kiểm tra phải là khái niệm độc lập. Nhưng tôi đã đọc về nó ở nhiều nơi .. đoán 'TDD phổ biến' là khá sai lầm - Gishu


The Mockery
Đôi khi chế nhạo có thể là tốt và tiện dụng. Nhưng đôi khi các nhà phát triển có thể mất chính mình và trong nỗ lực của họ để thử ra những gì không được thử nghiệm. Trong trường hợp này, một bài kiểm tra đơn vị chứa rất nhiều mock, stubs và / hoặc fakes rằng hệ thống đang được kiểm tra thậm chí không được thử nghiệm, thay vào đó dữ liệu được trả lại từ mocks là những gì đang được thử nghiệm.

Nguồn: bài đăng của James Carr.


56



Tôi tin rằng nguyên nhân của việc này là lớp học của bạn được kiểm tra có quá nhiều phụ thuộc. Thay thế được tái cấu trúc là trích xuất mã có thể bị cô lập. - Spoike
@Spoike; Nếu bạn đang ở trong một kiến ​​trúc phân lớp thực sự phụ thuộc vào vai trò của lớp; một số lớp có xu hướng có nhiều sự phụ thuộc hơn những lớp khác. - krosenvold
Tôi thấy gần đây, trong một blog được tôn trọng, việc tạo ra một thiết lập thực thể giả được trả về từ kho lưu trữ giả. WTF? Tại sao không chỉ khởi tạo một thực thể thực sự ở nơi đầu tiên. Bản thân tôi, tôi đã bị đốt cháy bởi một giao diện giả lập, nơi triển khai của tôi đã ném NotImplementedExceptions tất cả xung quanh. - Thomas Eyde
+1: xem thêm câu trả lời của tôi ở đây: stackoverflow.com/a/9702943/545127 - Raedwald


The Silent Catcher - Kelly?
Một thử nghiệm mà vượt qua nếu một ngoại lệ được ném .. ngay cả khi ngoại lệ thực sự xảy ra là một ngoại lệ khác với dự đoán của nhà phát triển.
Xem thêm: Bí mật Catcher

[Test]
[ExpectedException(typeof(Exception))]
public void ItShouldThrowDivideByZeroException()
{
   // some code that throws another exception yet passes the test
}

40



Đó là một trong những khó khăn và nguy hiểm (tức là làm cho bạn nghĩ rằng bạn đã thử nghiệm mã mà luôn luôn phát nổ mỗi khi nó chạy). Đó là lý do tại sao tôi cố gắng cụ thể về cả một lớp ngoại lệ và một cái gì đó duy nhất trong thông điệp. - Joshua Cheek


Thanh tra
Một thử nghiệm đơn vị vi phạm đóng gói trong nỗ lực để đạt được phạm vi mã 100%, nhưng biết rất nhiều về những gì đang xảy ra trong đối tượng mà bất kỳ nỗ lực nào để cấu trúc lại sẽ phá vỡ thử nghiệm hiện tại và yêu cầu bất kỳ thay đổi nào được phản ánh trong thử nghiệm đơn vị.


'làm thế nào để kiểm tra các biến thành viên của tôi mà không làm cho chúng công khai ... chỉ để kiểm tra đơn vị? '


34



Nguyên nhân: Ngạc nhiên ngớ ngẩn khi thử nghiệm hộp trắng. Có các công cụ để tạo ra các loại kiểm tra như Pex trên .NET. Giải pháp tái cấu trúc: Kiểm tra hành vi thay thế và nếu bạn thực sự cần kiểm tra các giá trị biên thì hãy để các công cụ tự động tạo phần còn lại. - Spoike
Trước khi Moq xuất hiện, tôi phải từ bỏ các khuôn khổ chế nhạo có lợi cho việc viết tay các mocks của tôi. Nó chỉ là quá dễ dàng để buộc thử nghiệm của tôi để thực hiện thực tế, làm cho bất kỳ refactoring bên cạnh không thể. Tôi không thể nói sự khác biệt, khác với Moq, tôi hiếm khi làm những loại sai lầm này. - Thomas Eyde


Thiết lập quá mức - James Carr
Một thử nghiệm đòi hỏi một thiết lập rất lớn để thậm chí bắt đầu thử nghiệm. Đôi khi hàng trăm dòng mã được sử dụng để chuẩn bị môi trường cho một thử nghiệm, với một số đối tượng liên quan, có thể gây khó khăn cho việc xác định những gì được kiểm tra do "tiếng ồn" của tất cả các thiết lập đang diễn ra. (Src: Bài đăng của James Carr)


34



Tôi hiểu rằng thiết lập kiểm tra quá mức thường trỏ đến a) mã có cấu trúc kém hoặc b) không đủ mocking, đúng không? - Topher Hunt
Mỗi tình huống có thể khác nhau. Nó có thể là do khớp nối cao. Nhưng thông thường nó là một trường hợp của overspecification, xác định (kỳ vọng giả) mỗi và mọi cộng tác viên trong kịch bản - cặp vợ chồng này thử nghiệm để thực hiện và làm cho họ dễ vỡ. Nếu cuộc gọi đến cộng tác viên là một chi tiết ngẫu nhiên đối với thử nghiệm, nó không được trong thử nghiệm. Điều này cũng giúp giữ cho bài kiểm tra ngắn và dễ đọc. - Gishu


Anal Probe

Một bài kiểm tra phải sử dụng các cách điên, bất hợp pháp hoặc không lành mạnh để thực hiện nhiệm vụ của mình như: Đọc các trường riêng bằng cách sử dụng Java setAccessible (đúng) hoặc mở rộng một lớp để truy cập các trường / phương thức được bảo vệ hoặc phải đặt thử nghiệm trong một gói nhất định để truy cập các trường / các phương thức toàn cục của gói.

Nếu bạn thấy mẫu này, các lớp đang được thử nghiệm sử dụng quá nhiều dữ liệu ẩn.

Sự khác biệt giữa điều này và Thanh tra là lớp đang được kiểm tra cố gắng che giấu ngay cả những thứ bạn cần kiểm tra. Vì vậy, mục tiêu của bạn không phải là để đạt được phạm vi kiểm tra 100% nhưng để có thể kiểm tra bất cứ điều gì cả. Hãy nghĩ đến một lớp chỉ có các trường riêng, run() phương pháp mà không có đối số và không có getters nào cả. Không có cách nào để kiểm tra điều này mà không vi phạm các quy tắc.


Gửi bởi Michael Borgwardt: Đây không thực sự là một mẫu thử nghiệm, nó thực dụng để giải quyết các thiếu sót trong mã đang được thử nghiệm. Tất nhiên nó là tốt hơn để sửa chữa những thiếu sót, nhưng điều đó có thể không được có thể trong trường hợp của các thư viện bên thứ 3.

Aaron Digulla: Tôi đồng ý. Có lẽ mục này thực sự phù hợp hơn với một wiki "JUnit HOWTO" và không phải là một mẫu giả mạo. Bình luận?


32



điều này không giống với Thanh tra? - Gishu
Hmm .. dòng này 'lớp kiểm tra cố gắng che giấu ngay cả những thứ bạn cần để kiểm tra' cho thấy một cuộc đấu tranh quyền lực giữa lớp và bài kiểm tra. Nếu nó cần được kiểm tra .. nó phải được công khai có thể truy cập bằng cách nào đó .. thông qua hành vi lớp / giao diện .. bằng cách nào đó mùi của vi phạm đóng gói - Gishu
nương náu: Maven2 có một plugin cho nó, phải không? - Aaron Digulla
Đây không thực sự là một mẫu thử nghiệm, nó thực dụng để giải quyết các thiếu sót trong mã đang được thử nghiệm. Tất nhiên nó là tốt hơn để sửa chữa những thiếu sót, nhưng điều đó có thể không được có thể trong trường hợp của các thư viện bên thứ 3. - Michael Borgwardt
IDK, nó phải có một số loại tác dụng phụ. Tôi muốn kiểm tra tác dụng phụ. Không chắc chắn ý của bạn về việc thử nghiệm API của bên thứ ba, tôi cho rằng bạn nên bọc mã đó vào mã của riêng mình mà bạn có thể kiểm tra được sử dụng đúng cách, sau đó tích hợp kiểm tra mã đó với API của bên thứ ba. Sẽ không đơn vị kiểm tra mã của bên thứ ba. - Joshua Cheek


Bài kiểm tra không có tên - Nick Pellow

Thử nghiệm được thêm vào để tạo lại một lỗi cụ thể trong trình theo dõi lỗi và tác giả của nó cho rằng không bảo đảm tên riêng của nó. Thay vì tăng cường kiểm tra hiện có, thiếu, một thử nghiệm mới được tạo ra có tên là testForBUG123.

Hai năm sau, khi kiểm tra đó không thành công, trước tiên bạn có thể cần thử và tìm BUG-123 trong trình theo dõi lỗi của bạn để tìm ra ý định của thử nghiệm.


26



Đúng vậy. Tho có ích hơn một chút so với bài kiểm tra gọi là "TestMethod" - NikolaiDante
trừ khi các thay đổi của trình gỡ lỗi, và bạn mất trình theo dõi cũ và các định danh sự cố của nó ... vì vậy DỰ ÁN-123 không còn có nghĩa là bất cứ điều gì .... - Chii