Đơn vị kiểm tra Danh mục chống mẫu


203

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

  • Một số mô hình hành động, quy trình hoặc cấu trúc lặp đi lặp lại ban đầu có vẻ 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 lại 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 Carrthảo luận liên quan về yahoogroup phát triển thử nghiệm

Nếu bạn đã tìm thấy một cái tên 'chưa được đặt tên' .. cũng vậy. Một bài đăng trên mỗi mẫu chống vui lòng làm cho số phiếu được tính cho một cái gì đó.

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


Aaron, bạn dường như là tất cả trong số này :) Sẽ là một ý tưởng tốt để thêm các dòng tag hoặc khẩu hiệu làm bình luận để chúng ta có thể ít cuộn hơn .. nói gì?
Gishu

1
Điều này đang đến khá tốt .. cảm ơn mọi người. Hãy tiếp tục đến .. một trong những bài viết SO thông tin nhất IMHO
Gishu

2
+1 yêu chủ đề này !!! Và hầu hết những điều này là rất đúng và thịnh hành quá!
Chii

Chủ đề tốt đẹp, tại sao cộng đồng wiki này mặc dù ???
Quibbledome

2
Vì đây là một cuộc thăm dò ý kiến ​​- bạn sẽ không muốn thu hoạch đại diện chỉ vì bạn đã đăng loại chống mẫu phổ biến nhất;)
Gishu

Câu trả lời:


70

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


67

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


15
Vâng, đó là một trong những yêu thích của tôi. Tôi làm nó suốt. Oh ... đợi đã ... bạn nói rằng đây là một điều xấu . :-)
guidoism

1
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 truesau mỗi cuộc gọi của trình biến đổi có thể. Vì vậy, bạn sẽ muốn kiểm tra xem mọi bất biến là truesau mỗi kết hợp dữ liệu biến đổi và dữ liệu đầu vào mà bạn đang kiểm tra. Nhưng bạn sẽ muốn giảm bớt sự trùng lặp và đảm bảo bạn kiểm tra tất cả các bất biến, bao gồm cả những người không hiện nguyên nhân thất bại thử nghiệm. Vì vậy, bạn đặt tất cả chúng trong một checkInvariants()chức năng xác minh và sử dụng nó trong mọi thử nghiệm. Mã thay đổi và một bất biến khác được thêm vào. Bạn đặt nó trong chức năng quá, tất nhiên. Nhưng nó là một tự do hơn.
Raedwald

2
@Raedwald - Theo thời gian, tên thử nghiệm không còn phù hợp với tất cả những thứ nó thử nghiệm. Ngoài ra, bạn có một số đập do các bài kiểm tra đan xen; 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ụ điển hình của bài kiểm tra 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 >> Act >> Khẳng định A >> Hành động thêm >> Xác nhận B >> Hành động thêm >> Xác nhận C. Bây giờ lý tưởng nếu A và C là bị hỏng, bạn sẽ thấy 2 lần thử nghiệm thất bại. Với bài kiểm tra trên, bạn chỉ thấy một, 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 khác nhau hợp nhất với nhau ..
Gishu

1
"Tên thử nghiệm không còn phù hợp với tất cả những thứ mà nó thử nghiệm" Chỉ khi thử nghiệm được đặt tên cho điều kiện bài đăng ban đầu. 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), 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 có thất bại khẳng định nào cho thấy nguyên nhân thất bại. Điều đó đòi hỏi một số nghiên cứu chi tiết về triển khai: gỡ lỗi cho lỗi thất bại hồi quy, kiến ​​thức của bạn về trạng thái phát triển cho một số công việc TDD.
Raedwald

64

Con đường hạnh phúc

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

JUnit Antipotypes


Nguyên nhân: Hoặc là hạn chế thời gian hoặc sự 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 thêm các bài kiểm tra để loại bỏ các kết quả dương tính giả. Nguyên nhân thứ hai cần một roi da. :)
Spoike

59

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à thử nghiệm vượt qua các hộp phát triển, nhưng thất bại khi ai đó cố gắng chạy nó ở nơi khác.

Phụ thuộc ẩn

Liên quan chặt chẽ đến 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 đưa vào đâu đó trước khi bài kiểm tra chạy. Nếu dữ liệu đó không được điền, thử nghiệm sẽ thất bại 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 lại buộc họ phải đào qua hàng mẫu mã để tìm ra dữ liệu mà nó được sử dụng đến từ đâu.


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


Đó 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 nói sẽ khiến người kiểm tra rời khỏi lưng bạn.)
Joris Timmermans

58

Chuỗi Gang

Một vài thử nghiệm phải chạy theo một thứ tự nhất định, tức là một thử nghiệm thay đổi trạng thái toàn cầu của hệ thống (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ì thực hiện khôi phục lại teardown(), các kiểm tra cam kết thay đổi của họ đối với cơ sở dữ liệu. Một nguyên nhân phổ biến khác là những thay đổi đối với trạng thái toàn cầu không được bao bọc trong các khối thử / cuối cùng để dọn dẹp nếu thử nghiệm thất bại.


Điều này chỉ đơn giản là khó chịu .. Phá vỡ 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' khá là rắc rối
Gishu

56

Mockery
Đôi khi chế giễu có thể tốt và tiện dụng. Nhưng đôi khi các nhà phát triển có thể đánh mất chính họ và trong nỗ lực của họ để chế nhạo 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 giả, sơ khai và / hoặc giả mà hệ thống được kiểm tra thậm chí không được kiểm tra, thay vào đó dữ liệu được trả về từ giả là những gì đang được kiểm tra.

Nguồn: Bài viết của James Carr.


2
Tôi tin rằng nguyên nhân của việc này là lớp học của bạn đang có quá nhiều phụ thuộc. Tái cấu trúc thay thế là để trích xuất mã có thể được phân 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 phụ thuộc nhiều hơn các 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ừ mộ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. Chính tôi, tôi vừa bị đốt cháy bởi một giao diện bị chế giễu, nơi việc triển khai của tôi đang ném NotImcellenceedExceptions xung quanh.
Thomas Eyde

40

Người bắt im lặng - Kelly?
Một thử nghiệ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 thử nghiệm mà nhà phát triển dự định.
Xem thêm: Bí mật bắt bóng

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

Đó là một điều khó khăn và nguy hiểm (nghĩa là khiến bạn nghĩ rằng bạn đã kiểm tra mã 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ì đó độc đáo trong tin nhắn.
Joshua Cheek

34

Thanh tra
Một thử nghiệm đơn vị vi phạm đóng gói trong nỗ lực đạt được phạm vi bao phủ 100% mã, nhưng biết rất nhiều về những gì đang diễn ra trong đối tượng mà bất kỳ nỗ lực tái cấu trúc nào 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 đơn vị kiểm tra.


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


2
Nguyên nhân: Sự phụ thuộc vô lý vào thử nghiệm hộp trắng. Có các công cụ để tạo các loại thử nghiệm như Pex trên .NET. Giải pháp tái cấu trúc: Thay vào đó hãy kiểm tra hành vi và nếu bạn thực sự cần kiểm tra giá trị biên thì hãy để các công cụ tự động tạo phần còn lại.
Spoike

1
Trước khi Moq xuất hiện, tôi đã phải từ bỏ các khuôn khổ chế giễu để ủng hộ việc viết tay các giả của mình. Thật quá dễ dàng để buộc các thử nghiệm của tôi với việc thực hiện thực tế, khiến cho bất kỳ tái cấu trúc nào bên cạnh là không thể. Tôi không thể nói sự khác biệt, ngoài Moq, tôi hiếm khi mắc phải những sai lầm này.
Thomas Eyde

34

Cài đặt quá mức - James Carr
Một thử nghiệm yêu cầu một thiết lập 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 có liên quan, điều này 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 của James Carr )


Tôi hiểu rằng thiết lập thử nghiệm quá mức thường chỉ đến a) mã có cấu trúc kém hoặc b) không đủ chế độ chế giễu, đúng không?
Topher Hunt

Vâng 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, đó là một trường hợp quá mức, chỉ định (giả định kỳ vọng) mỗi và mọi cộng tác viên trong kịch bản - điều này kết hợp thử nghiệm để thực hiện và làm cho chúng 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 cho bài kiểm tra, thì nó không nên nằm trong bài kiểm tra. Điều này cũng giúp giữ cho bài kiểm tra ngắn và dễ đọc.
Gishu

32

Thăm dò hậu môn

Một thử nghiệm phải sử dụng các cách điên rồ, 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 setAccessible (true) của Java 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 gói trường / phương pháp toàn cầu.

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

Sự khác biệt giữa cái này và The Inspector là lớp đượ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% mà là có thể kiểm tra mọi thứ. Hãy nghĩ về một lớp chỉ có các trường riêng, một run()phương thức 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.


Nhận xét của Michael Borgwardt: Đây thực sự không phải là một antipotype thử nghiệm, đó là chủ nghĩa thực dụng để đối phó với sự thiếu sót trong mã đang được thử nghiệm. Tất nhiên là tốt hơn để khắc phục những thiếu sót đó, nhưng điều đó có thể không thể xảy ra trong trường hợp thư viện của 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 wiki "JUnit HOWTO" chứ không phải là một antipotype. Bình luận?


Đây không giống như Thanh tra sao?
Gishu

1
Hmm .. dòng này 'lớp đang thử nghiệm cố gắng che giấu ngay cả những thứ bạn cần kiểm tra' biểu thị 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ó có thể được truy cập công khai bằng cách nào đó .. thông qua hành vi / giao diện lớp .. điều này bằng cách nào đó có mùi của việc đóng gói vi phạm
Gishu

2
npellow: Maven2 có một plugin cho điều đó, phải không?
Aaron Digulla

1
Đây không thực sự là một antipotype thử nghiệm, đó là chủ nghĩa thực dụng để đối phó với những thiếu sót trong mã đang được thử nghiệm. Tất nhiên là tốt hơn để khắc phục những thiếu sót đó, nhưng điều đó có thể không thể xảy ra trong trường hợp thư viện của bên thứ 3.
Michael Borgwardt

1
IDK, nó phải có một số loại tác dụng phụ. Tôi sẽ kiểm tra tác dụng phụ. Không chắc ý của bạn về việc kiểm tra API của bên thứ ba, tôi cho rằng bạn nên bọc nó trong mã của riêng bạn 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ã bên thứ ba.
Joshua Cheek

26

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

Thử nghiệm được thêm vào để tái tạo một lỗi cụ thể trong trình theo dõi lỗi và tác giả cho rằng không đảm bảo tên của chính 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 thử nghiệm đó thất bại, 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.


7
Thật vậy. Tho là hữu ích hơn một chút so với một thử nghiệm gọi là "TestMethod"
NikolaiDante

8
trừ khi bugtracker thay đổi và bạn mất trình theo dõi cũ và các số nhận dạng vấn đề của nó ... vì vậy DỰ ÁN-123 không còn có nghĩa gì nữa ....
Chii

25

Chọc chậm

Một bài kiểm tra đơn vị chạy cực kỳ chậm. Khi các nhà phát triển khởi động nó, họ có thời gian để đi vào phòng tắm, hút thuốc hoặc tệ hơn là đá thử trước khi về nhà vào cuối ngày. (Src: bài của James Carr )

aka các bài kiểm tra sẽ không được chạy thường xuyên như họ nên


Một số thử nghiệm chạy chậm bởi bản chất của chúng. Nếu bạn quyết định không chạy chúng thường xuyên như những cái khác, thì hãy chắc chắn rằng chúng ít nhất chạy trên máy chủ CI càng thường xuyên càng tốt.
Chris Vest

Đây là một câu hỏi rõ ràng nhưng những cách chung nhất để khắc phục điều này là gì?
Topher Hunt

Điều này ban đầu có vẻ có lợi, nhỉ?
Kev

1
@TopherHunt Thông thường các bài kiểm tra chậm vì chúng có một số phụ thuộc đắt tiền (ví dụ: hệ thống tập tin, cơ sở dữ liệu). Bí quyết là phân tích các phụ thuộc cho đến khi bạn nhìn thấy vấn đề, sau đó đẩy sự phụ thuộc lên bảng gọi. Tôi đã viết một nghiên cứu trường hợp trong đó các học sinh của tôi đã lấy bộ bài kiểm tra đơn vị của họ từ 77 giây đến 0,01 giây bằng cách sửa các phụ thuộc của họ: github.com/JoshCheek/fast_tests
Joshua Cheek

20

Con bướm

Bạn phải kiểm tra thứ gì đó chứa dữ liệu thay đổi mọi lúc, như cấu trúc chứa ngày hiện tại và không có cách nào để đưa kết quả xuống một giá trị cố định. Phần xấu xí là bạn hoàn toàn không quan tâm đến giá trị này. Nó chỉ làm cho bài kiểm tra của bạn phức tạp hơn mà không cần thêm bất kỳ giá trị nào.

Con dơi cánh của nó có thể gây ra một cơn bão ở phía bên kia của thế giới. - Edward Lorenz, Hiệu ứng cánh bướm


Mô hình chống ở đây là gì: Một bài kiểm tra như thế này trông như thế nào? Có sửa chữa không? Có bất kỳ lợi thế có thể tranh cãi nào đối với thử nghiệm dưới mã để System.DateTime.Nowxác định sự phụ thuộc như thế nào , bên cạnh việc có các thử nghiệm đơn vị đơn giản hơn hoặc xác định hơn không?
Merlyn Morgan-Graham

1
Trong Java, một ví dụ sẽ là gọi toString()một đối tượng không ghi đè lên phương thức. Điều đó sẽ cung cấp cho bạn ID của đối tượng phụ thuộc vào địa chỉ bộ nhớ. Hoặc toString()chứa khóa chính của đối tượng và thay đổi mỗi khi bạn chạy thử nghiệm. Có ba cách để khắc phục điều này: 1. Thay đổi mã bạn đang kiểm tra, 2. sử dụng regrec để loại bỏ các phần biến của kết quả kiểm tra hoặc 3. sử dụng các công cụ mạnh mẽ để ghi đè lên các dịch vụ hệ thống để làm cho chúng trả về kết quả có thể dự đoán được.
Aaron Digulla

Nguyên nhân cơ bản của việc chống mẫu này là do mã được kiểm tra không quan tâm đến việc thử nghiệm nó có bao nhiêu nỗ lực. Vì vậy, ý thích của một nhà phát triển là cánh bướm gây ra vấn đề ở nơi khác.
Aaron Digulla

19

Thử nghiệm nhấp nháy (Nguồn: Romilly Cocking)

Một bài kiểm tra đôi khi không thành công, không phải vào thời điểm cụ thể và thường là do điều kiện cuộc đua trong bài kiểm tra. Thường xảy ra khi kiểm tra một cái gì đó không đồng bộ, chẳng hạn như JMS.

Có thể là một siêu thiết lập cho mẫu chống ' Chờ và Xem ' và mẫu chống ' Người ngủ '.

Việc xây dựng thất bại, oh tốt, chỉ cần chạy lại xây dựng. - Nhà phát triển ẩn danh


@Stuart - một video phải xem mô tả đây là "Xe bị đình trệ - Thử ngay!" videosift.com/video/ước Mẫu này cũng có thể được gọi là "Thử ngay!" hoặc chỉ - "Thử nghiệm
Flakey

1
Tôi đã từng viết một bài kiểm tra cho một PRGN đảm bảo phân phối thích hợp. Đôi khi, nó sẽ thất bại một cách ngẫu nhiên. Đi hình. :-)
Chris Vest

1
Đây sẽ không phải là một thử nghiệm tốt để có? Nếu một bài kiểm tra thất bại, bạn cần theo dõi nguồn gốc của vấn đề. Tôi đã chiến đấu với ai đó về một bài kiểm tra thất bại trong khoảng thời gian từ 9p đến nửa đêm. Ông nói rằng đó là ngẫu nhiên / không liên tục. Cuối cùng nó đã được bắt nguồn từ một lỗi liên quan đến múi giờ. Đi hình.
Trenton

@Christian Vest Hansen: bạn không thể gieo nó?
Andrew Grimm

@trenton Đây chỉ là một thử nghiệm tốt nếu các nhà phát triển có thể bận tâm theo dõi nó, thay vì chỉ bỏ qua nó (mà họ có thể thoát khỏi, vì nó hầu hết thời gian).
Will Sheppard

19

Chờ và xem

Một thử nghiệm chạy một số mã được thiết lập và sau đó cần phải 'chờ' một khoảng thời gian cụ thể trước khi nó có thể 'nhìn thấy' nếu mã được thử nghiệm hoạt động như mong đợi. Một testMethod sử dụng Thread.s ngủ () hoặc tương đương chắc chắn là một thử nghiệm "Chờ và Xem".

Thông thường, bạn có thể thấy điều này nếu kiểm tra là mã kiểm tra tạo ra một sự kiện bên ngoài hệ thống như email, yêu cầu http hoặc ghi tệp vào đĩa.

Thử nghiệm như vậy cũng có thể là Anh hùng cục bộ vì nó sẽ FAIL khi chạy trên hộp chậm hơn hoặc máy chủ CI quá tải.

Không nên nhầm lẫn kiểu chống chờ và xem với The Sleeper .


Hmm .. tôi cũng sử dụng một cái gì đó như thế này. Làm thế nào khác tôi có thể kiểm tra mã đa luồng?
Gishu

@Gishu, bạn có thực sự muốn kiểm tra đơn vị nhiều luồng chạy đồng thời không? Tôi cố gắng chỉ kiểm tra đơn vị bất cứ phương thức run () nào trong sự cô lập. Một cách dễ dàng để làm điều này là bằng cách gọi run () - sẽ chặn, thay vì start () từ bài kiểm tra đơn vị.
npellow

@Gishu sử dụng CountDownLatches, Semaphores, condition hoặc tương tự, để các chủ đề nói với nhau khi chúng có thể chuyển sang cấp độ tiếp theo.
Chris Vest

Một ví dụ: madcoderspeak.blogspot.com/2008/11/ Nút bia bia evt. Người quan sát đang bỏ phiếu trong các khoảng thời gian và đưa ra các sự kiện đã thay đổi .. trong trường hợp đó tôi thêm một độ trễ để các chủ đề bỏ phiếu có cơ hội chạy trước khi thoát khỏi bài kiểm tra.
Gishu

Tôi nghĩ rằng các liên kết phim hoạt hình bị hỏng.
Andrew Grimm

17

Lịch thi đấu được chia sẻ không phù hợp - Tim Ottinger
Một số trường hợp kiểm tra trong lịch thi kiểm tra thậm chí không sử dụng hoặc không cần thiết lập / phá bỏ. Một phần do quán tính của nhà phát triển để tạo ra một vật cố thử nghiệm mới ... dễ dàng hơn khi chỉ cần thêm một trường hợp thử nghiệm vào đống


1
Nó cũng có thể là lớp đang thử nghiệm đang cố gắng làm quá nhiều.
Mike Two

16

Người khổng lồ

Một thử nghiệm đơn vị, mặc dù nó đang kiểm tra hợp lệ đối tượng được thử nghiệm, có thể trải rộng hàng ngàn dòng và chứa nhiều trường hợp thử nghiệm. Đây có thể là một chỉ báo cho thấy hệ thống đang được thử nghiệm là một Vật thể (bài của James Carr).

Một dấu hiệu chắc chắn cho điều này là một thử nghiệm kéo dài hơn một vài dòng mã. Thông thường, bài kiểm tra phức tạp đến mức nó bắt đầu chứa các lỗi về hành vi của chính nó hoặc không ổn định.


15

Tôi sẽ tin điều đó khi tôi thấy một số GUI nhấp nháy
Một sự cố định / ám ảnh không lành mạnh khi thử nghiệm ứng dụng thông qua GUI của nó 'giống như một người dùng thực sự'

Kiểm tra các quy tắc kinh doanh thông qua GUI là một hình thức khớp nối khủng khiếp . Nếu bạn viết hàng ngàn bài kiểm tra thông qua GUI và sau đó thay đổi GUI của bạn, hàng ngàn bài kiểm tra sẽ bị hỏng.
Thay vào đó, chỉ kiểm tra những thứ GUI thông qua GUI và ghép GUI thành một hệ thống giả thay vì hệ thống thực, khi bạn chạy các thử nghiệm đó. Kiểm tra các quy tắc kinh doanh thông qua API không liên quan đến GUI. - Bob Martin

Bạn phải hiểu rằng nhìn thấy là tin tưởng, nhưng cũng phải biết rằng tin là nhìn thấy. - Wait Waitley


1
Nếu bạn nghĩ GUI nhấp nháy là sai, tôi đã thấy ai đó đã viết bài kiểm tra jUnit khởi động GUI và cần tương tác người dùng để tiếp tục. Nó treo phần còn lại của bộ thử nghiệm. Quá nhiều cho tự động hóa thử nghiệm!
Spoike

Tôi không đồng ý. Kiểm tra GUI rất khó, nhưng chúng cũng là một nguồn gây ra lỗi. Không kiểm tra chúng chỉ là lười biếng.
Ray

3
vấn đề ở đây là bạn không nên kiểm tra GUI mà là bạn không nên chỉ kiểm tra qua GUI. Bạn có thể thực hiện kiểm tra 'không đầu' với GUI. Giữ GUI càng mỏng càng tốt - sử dụng hương vị của MVP - sau đó bạn có thể thoát khỏi việc không kiểm tra nó. Nếu bạn thấy rằng bạn luôn gặp lỗi khi cắt lớp GUI mỏng, hãy che nó bằng các bài kiểm tra .. nhưng hầu hết thời gian, tôi không thấy nó đáng để nỗ lực. Lỗi 'nối dây' GUI thường dễ khắc phục hơn ...
Gishu

@Spoike: Các thử nghiệm thủ công có hướng dẫn không tệ, cũng không sử dụng jUnit (hoặc bất kỳ khung thử nghiệm đơn vị nào khác) để lái thử nghiệm tự động không thử nghiệm đơn vị. Bạn không nên đặt những thứ đó trong cùng một dự án, cũng không coi chúng như các bài kiểm tra đơn vị (ví dụ: chạy liên tục hoặc sau mỗi bản dựng).
Merlyn Morgan-Graham ngày

1
@ MerlynMorgan-Graham Tôi đồng ý và tôi không có nghĩa là bạn không nên kiểm tra GUI. Niềm tin của các thành viên trong nhóm rằng việc kết hợp các bài kiểm tra thủ công có hướng dẫn với các bài kiểm tra tự động là ổn, đã làm tôi băn khoăn. Sau đó tôi đã phát hiện ra rằng đó là một cách tuyệt vời để khiến tất cả những người không quen sử dụng TDD ngừng sử dụng nó. Tôi thấy rằng việc trộn các bài kiểm tra chức năng (dễ bay hơi) với các bài kiểm tra đơn vị (được cho là ổn định) là không tốt nếu bạn muốn theo quy trình TDD.
Spoike

14

Người ngủ, còn gọi là núi Vesuvius - Nick Pellow

Một bài kiểm tra được định sẵn để FAIL vào một số thời gian và ngày cụ thể trong tương lai. Điều này thường xảy ra do kiểm tra giới hạn không chính xác khi kiểm tra mã sử dụng đối tượng Ngày hoặc Lịch. Đôi khi, bài kiểm tra có thể thất bại nếu chạy vào một thời điểm rất cụ thể trong ngày, chẳng hạn như nửa đêm.

'Người ngủ' không bị nhầm lẫn với mô hình chống ' Chờ và Xem '.

Mã đó sẽ được thay thế từ lâu trước năm 2000 - Nhiều nhà phát triển vào năm 1960


Tôi muốn gọi đây là một Núi lửa không hoạt động :) .. nhưng tôi biết những gì bạn đang nói về .. ví dụ: một ngày được chọn làm ngày thử nghiệm trong tương lai tại thời điểm viết sẽ trở thành một ngày hiện tại / quá khứ khi ngày đó đi qua .. phá vỡ bài kiểm tra. Bạn có thể gửi một ví dụ .. chỉ để minh họa điều này.
Gishu

@Gishu - +1. Tôi cũng nghĩ như vậy, nhưng không thể quyết định giữa hai người. Tôi đã cập nhật tiêu đề để làm cho điều này rõ ràng hơn một chút;)
vào

11

Cây chết

Một bài kiểm tra nơi sơ khai đã được tạo, nhưng bài kiểm tra không thực sự được viết.

Tôi thực sự đã thấy điều này trong mã sản xuất của chúng tôi:

class TD_SomeClass {
  public void testAdd() {
    assertEquals(1+1, 2);
  }
}

Tôi thậm chí không biết phải nghĩ gì về điều đó.


8
:) - còn được gọi là Cửa hậu tuân thủ quy trình.
Gishu

1
Chúng tôi đã có một ví dụ về điều này gần đây trong một thử nghiệm và thử nghiệm theo phương pháp đã được tái cấu trúc nhiều lần. Sau một vài lần lặp lại, thử nghiệm đã trở thành một cuộc gọi đến thử nghiệm theo phương pháp. Và bởi vì phương thức hiện đã trả về khoảng trống, nên không có bất kỳ xác nhận nào được xác nhận. Về cơ bản, thử nghiệm chỉ đảm bảo phương pháp không đưa ra một ngoại lệ. Không quan trọng nếu nó thực sự làm bất cứ điều gì hữu ích hoặc chính xác. Tôi tìm thấy nó trong đánh giá mã và hỏi, "Vậy ... chúng ta thậm chí đang thử nghiệm gì ở đây?"
Marvo

11

có một chút bởi điều này ngày hôm nay:

Sàn ướt :
Thử nghiệm tạo dữ liệu được duy trì ở đâu đó, nhưng thử nghiệm không dọn sạch khi kết thúc. Điều này khiến các bài kiểm tra (cùng bài kiểm tra hoặc có thể các bài kiểm tra khác) không thành công trong các lần kiểm tra tiếp theo .

Trong trường hợp của chúng tôi, thử nghiệm đã để lại một tệp nằm xung quanh thư mục "temp", với sự cho phép từ người dùng đã chạy thử nghiệm lần đầu tiên. Khi một người dùng khác cố gắng thử nghiệm trên cùng một máy: boom. Trong các bình luận trên trang của James Carr, Joakim Ohlrogge gọi đây là "Công nhân cẩu thả", và nó là một phần của cảm hứng cho "Thức ăn thừa hào phóng". Tôi thích tên của tôi cho nó tốt hơn (ít xúc phạm hơn, quen thuộc hơn).


Bạn có thể sử dụng quy tắc thư mục tạm thời của Junit để tránh sàn ướt.
DaveFar

Loại này liên quan đến một mô hình chống tích hợp liên tục. Trong CI, mỗi nhà phát triển nên có không gian làm việc và tài nguyên của riêng mình và máy xây dựng cũng phải là môi trường của riêng họ. Sau đó, bạn tránh những thứ như vấn đề về sự cho phép (hoặc có thể cuối cùng bạn sẽ giấu chúng để chúng chỉ xuất hiện trong sản xuất.)
Marvo

11

The Cuckoo - Frank Carver
Một thử nghiệm đơn vị nằm trong một trường hợp thử nghiệm với một số thử nghiệm khác và thích quá trình thiết lập (có khả năng dài) như các thử nghiệm khác trong trường hợp thử nghiệm, nhưng sau đó loại bỏ một số hoặc tất cả các tạo phẩm khỏi thiết lập và tạo riêng của nó.
Triệu chứng nâng cao của: Lịch thi đấu được chia sẻ không phù hợp


10

The Secret Catch - Frank Carver
Một thử nghiệm mà thoạt nhìn dường như không thực hiện thử nghiệm nào, do không có xác nhận. Nhưng "Ma quỷ nằm trong chi tiết" .. thử nghiệm thực sự dựa vào một ngoại lệ được ném ra và mong đợi khung thử nghiệm nắm bắt ngoại lệ và báo cáo cho người dùng là thất bại.

[Test]
public void ShouldNotThrow()
{
   DoSomethingThatShouldNotThrowAnException();
}

2
Trên thực tế, đây có thể là một bài kiểm tra hợp lệ - đặc biệt là bài kiểm tra hồi quy.
Ilja Preuß

xin lỗi một lần nữa khiến điều này bị nhầm lẫn với Trình bắt im lặng ... các bài kiểm tra đơn vị nên nêu rõ ý định về những gì đang được kiểm tra thay vì nói 'điều này sẽ hoạt động' .. (+1 tp một cái gì đó tốt hơn không có gì. Đặc biệt nếu bạn đang hồi quy cũ quốc gia)
Gishu

1
Trong các loại thử nghiệm này, tôi ít nhất bắt được Ngoại lệ và gán nó cho một biến. Sau đó tôi khẳng định không null.
Thomas Eyde

4
Một số khung có một Assert.DoesNotThrow(SomeDelegateType act)xác nhận kiểu có thể được sử dụng cụ thể trong các trường hợp như thế này. Tôi thấy điều này ít tổng hơn so với việc có một trường hợp thử nghiệm thành công khi một hàm tạo trả về không null, nhưng thất bại khi hàm tạo ném. Một constructor sẽ không bao giờ trả về null. (Lưu ý: chỉ áp dụng cho các ngôn ngữ mà nhà xây dựng được đảm bảo trả về giá trị không null)
Merlyn Morgan-Graham

10

Vụ phá hoại môi trường

Một thử nghiệm 'đơn vị' cho các 'yêu cầu' khác nhau bắt đầu tràn ra môi trường của nó, sử dụng và thiết lập các biến / cổng môi trường. Chạy hai trong số các thử nghiệm này đồng thời sẽ gây ra ngoại lệ 'cổng không khả dụng', v.v.

Các thử nghiệm này sẽ không liên tục và khiến các nhà phát triển nói những điều như 'chỉ cần chạy lại'.

Một giải pháp mà tôi đã thấy là chọn ngẫu nhiên một số cổng để sử dụng. Điều này làm giảm khả năng xảy ra xung đột, nhưng rõ ràng không giải quyết được vấn đề. Vì vậy, nếu bạn có thể, hãy luôn giả lập mã để nó không thực sự phân bổ tài nguyên không thể thay đổi.


@gcrain .. các xét nghiệm nên có tính quyết định. IMO một cách tiếp cận tốt hơn sẽ là sử dụng cổng 'nổi tiếng trong nhóm' để kiểm tra và dọn dẹp trước và sau khi kiểm tra một cách chính xác sao cho nó luôn có sẵn ...
Gishu

1
@gishu - vấn đề không phải là không có phương thức setup () và torndown () để xử lý bằng các cổng này. ví dụ, vấn đề là chạy máy chủ CI và nhiều phiên bản thử nghiệm chạy cùng một lúc, cố gắng sử dụng cùng một số cổng thử nghiệm được
mã hóa cứng

10

Bài kiểm tra Turing

Một testcase được tạo tự động bởi một số công cụ đắt tiền có nhiều, nhiều khẳng định đã lượm lặt được từ lớp đang thử nghiệm bằng cách sử dụng một số phân tích luồng dữ liệu quá thông minh. Lulls các nhà phát triển vào một cảm giác sai lầm về niềm tin rằng mã của họ đã được kiểm tra tốt, loại bỏ họ khỏi trách nhiệm thiết kế và duy trì các bài kiểm tra chất lượng cao. Nếu máy có thể viết bài kiểm tra cho bạn, tại sao máy không thể rút ngón tay ra và tự viết ứng dụng!

Xin chào ngu ngốc. - Máy tính thông minh nhất thế giới đến người học việc mới (từ truyện tranh Amiga cũ).


10

Bài kiểm tra cực bốn mươi

Sợ đến quá gần với lớp mà họ đang cố kiểm tra, các bài kiểm tra này hoạt động ở khoảng cách xa, cách nhau bởi vô số lớp trừu tượng và hàng ngàn dòng mã từ logic họ đang kiểm tra. Vì vậy, chúng cực kỳ dễ vỡ và dễ bị ảnh hưởng bởi tất cả các loại tác dụng phụ xảy ra trên hành trình sử thi đến và từ lớp học quan tâm.


9

Doppelgänger

Để kiểm tra một cái gì đó, bạn phải sao chép các phần của mã được kiểm tra vào một lớp mới có cùng tên và gói và bạn phải sử dụng phép thuật classpath hoặc trình nạp lớp tùy chỉnh để đảm bảo nó hiển thị trước (vì vậy bản sao của bạn được chọn lên).

Mẫu này cho biết số lượng phụ thuộc ẩn không lành mạnh mà bạn không thể kiểm soát từ một bài kiểm tra.

Tôi nhìn mặt anh ... mặt tôi! Nó giống như một tấm gương nhưng làm cho máu của tôi đóng băng.


7

The Hen Hen - Frank Carver
Một thiết lập phổ biến hơn nhiều so với các trường hợp thử nghiệm thực tế cần. Ví dụ: tạo tất cả các loại cấu trúc dữ liệu phức tạp có các giá trị rõ ràng và duy nhất quan trọng khi các thử nghiệm chỉ khẳng định sự hiện diện hay vắng mặt của một cái gì đó.
Triệu chứng nâng cao của: Lịch thi đấu được chia sẻ không phù hợp

Tôi không biết nó làm gì ... Dù sao tôi cũng đang thêm nó, chỉ trong trường hợp. - Nhà phát triển ẩn danh


7

Bài kiểm tra tất cả

Tôi không thể tin rằng điều này đã không được đề cập cho đến bây giờ, nhưng các thử nghiệm không nên phá vỡ Nguyên tắc Trách nhiệm duy nhất .

Tôi đã bắt gặp điều này rất nhiều lần, các bài kiểm tra phá vỡ quy tắc này theo định nghĩa là một cơn ác mộng cần duy trì.


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.