Nếu mã kiểm tra đơn vị của bạn có mùi thì mùi có thực sự quan trọng không?


52

Thông thường tôi chỉ cần ném các bài kiểm tra đơn vị của mình với nhau bằng cách sử dụng bản sao và dán và tất cả các loại thực hành xấu khác. Các bài kiểm tra đơn vị thường kết thúc trông khá xấu xí, chúng đầy "mùi mã", nhưng điều này có thực sự quan trọng không? Tôi luôn tự nhủ với điều kiện mã "thực" là "tốt" mới là vấn đề. Thêm vào đó, kiểm tra đơn vị thường yêu cầu nhiều "hack" khác nhau như các chức năng khai thác.

Làm thế nào tôi có thể quan tâm đến các bài kiểm tra đơn vị được thiết kế kém ("có mùi")?


8
Làm thế nào khó khăn để sửa mã bạn luôn sao chép?
JeffO

7
Mùi mã trong các thử nghiệm có thể dễ dàng là một chỉ báo về mùi ẩn trong phần còn lại của mã - tại sao tiếp cận các thử nghiệm như thể chúng không phải là mã "thực"?
HorusKol

Câu trả lời:


75

Là thử nghiệm đơn vị có mùi quan trọng? Vâng chắc chắn. Tuy nhiên, chúng khác với mùi mã vì các thử nghiệm đơn vị phục vụ một mục đích khác và có một bộ căng thẳng khác nhau thông báo cho thiết kế của chúng. Nhiều mùi trong mã không áp dụng cho các bài kiểm tra. Với TDD tâm lý của tôi, tôi sẽ thực sự cho rằng mùi đơn vị kiểm tra được nhiều quan trọng hơn so với mã mùi vì mã là chỉ có mặt để đáp ứng các bài kiểm tra.

Dưới đây là một số mùi thử nghiệm đơn vị phổ biến:

  • Tính mong manh : các thử nghiệm của bạn có thất bại thường xuyên và bất ngờ ngay cả đối với các thay đổi mã có vẻ tầm thường hoặc không liên quan?
  • Rò rỉ trạng thái : các bài kiểm tra của bạn thất bại khác nhau tùy thuộc vào, ví dụ, thứ tự chúng được chạy?
  • Setup / Teardown Bloat : Các khối thiết lập / xé của bạn có dài và phát triển lâu hơn không? Họ có thực hiện bất kỳ loại logic kinh doanh?
  • Thời gian chạy chậm : Các bài kiểm tra của bạn có mất nhiều thời gian để chạy không? Có bất kỳ bài kiểm tra đơn vị cá nhân nào của bạn mất nhiều thời gian hơn một phần mười giây để chạy không? (Vâng, tôi nghiêm túc, một phần mười giây.)
  • Ma sát : Các bài kiểm tra hiện tại có gây khó khăn cho việc viết bài kiểm tra mới không? Bạn có thấy mình phải vật lộn với thất bại kiểm tra thường xuyên trong khi tái cấu trúc không?

Tầm quan trọng của mùi là chúng là những chỉ số hữu ích của thiết kế hoặc các vấn đề cơ bản khác, tức là "nơi có khói, có lửa". Đừng chỉ tìm kiếm mùi thử nghiệm, hãy tìm nguyên nhân cơ bản của chúng.

Mặt khác, đây là một số thực tiễn tốt cho các bài kiểm tra đơn vị:

  • Phản hồi nhanh, tập trung : Các bài kiểm tra của bạn sẽ nhanh chóng cách ly sự thất bại và cung cấp cho bạn thông tin hữu ích về nguyên nhân của nó.
  • Giảm thiểu khoảng cách mã kiểm tra : Cần có một đường dẫn rõ ràng và ngắn giữa thử nghiệm và mã thực hiện nó. Khoảng cách dài tạo ra các vòng phản hồi dài không cần thiết.
  • Kiểm tra một điều tại một thời điểm : Các bài kiểm tra đơn vị chỉ nên kiểm tra một điều. Nếu bạn cần kiểm tra một điều khác, viết một bài kiểm tra khác.
  • Một lỗi là một bài kiểm tra bạn quên viết : Bạn có thể học được gì từ thất bại này để viết các bài kiểm tra tốt hơn, hoàn thiện hơn trong tương lai?

2
"Các bài kiểm tra đơn vị phục vụ một mục đích khác nhau và có một tập hợp căng thẳng khác nhau thông báo cho thiết kế của họ". Ví dụ, họ nên DAMP, không nhất thiết phải DRY.
Jörg W Mittag

3
@ Jorg Đồng ý, nhưng DAMP có thực sự đại diện cho điều gì không? : D
Rein Henrichs

5
@Rein: Các cụm từ mô tả và có ý nghĩa. Ngoài ra, không hoàn toàn KHÔ. Xem codeshelter.wordpress.com/2011/04/07/ khăn
Robert Harvey

+1. Tôi cũng không biết ý nghĩa của DAMP.
egarcia

2
@ironcode Nếu bạn không thể làm việc trên một hệ thống một cách cô lập mà không sợ phá vỡ sự tích hợp của nó với các hệ thống khác, nó có mùi giống như khớp nối chặt chẽ với tôi. Đây chính xác là mục đích của việc xác định mùi thử nghiệm giống như thời gian chạy dài: chúng thông báo cho bạn về các vấn đề thiết kế như khớp nối chặt chẽ. Câu trả lời không nên là "Ồ, vậy thì mùi thử nghiệm đó không hợp lệ", nó phải là "Mùi này cho tôi biết gì về thiết kế của tôi?" Các thử nghiệm đơn vị xác định giao diện bên ngoài của hệ thống của bạn phải đủ để cho bạn biết liệu các thay đổi của bạn có phá vỡ sự tích hợp với người tiêu dùng hay không.
Rein Henrichs

67

Được quan tâm. Bạn viết các bài kiểm tra đơn vị để chứng minh mã của bạn hoạt động theo cách bạn mong đợi. Chúng cho phép bạn tái cấu trúc nhanh chóng với sự tự tin. Nếu các bài kiểm tra của bạn mong manh, khó hiểu hoặc nếu chúng khó bảo trì, bạn sẽ bỏ qua các bài kiểm tra thất bại hoặc tắt chúng khi cơ sở mã của bạn phát triển, phủ nhận nhiều lợi ích của việc viết bài kiểm tra ở nơi đầu tiên.


17
+1 Khoảnh khắc bạn bắt đầu bỏ qua các bài kiểm tra thất bại, họ không thêm bất kỳ giá trị nào.

19

Tôi vừa đọc xong Nghệ thuật kiểm tra đơn vị vài ngày trước. Tác giả chủ trương đặt nhiều sự quan tâm vào các bài kiểm tra đơn vị của bạn khi bạn thực hiện mã sản xuất của mình.

Tôi đã trải qua các bài kiểm tra viết kém, không thể nhầm lẫn được. Tôi đã viết một số của riêng tôi. Nó hầu như đảm bảo rằng nếu một bài kiểm tra là một nỗi đau ở mông để duy trì, nó sẽ không được duy trì. Khi các bài kiểm tra không đồng bộ với mã được kiểm tra, chúng sẽ trở thành tổ của sự dối trá và lừa dối. Toàn bộ quan điểm của các bài kiểm tra đơn vị là để củng cố niềm tin rằng chúng tôi chưa phá vỡ bất cứ điều gì (nghĩa là chúng tạo ra niềm tin). Nếu các bài kiểm tra không thể tin cậy được, thì chúng còn tệ hơn là vô dụng.


4
+1 bạn phải duy trì các bài kiểm tra, giống như mã sản xuất
Hamish Smith

Một cuốn sách rất hay khác về chủ đề này là "các mẫu thử nghiệm xUnit - Mã kiểm tra lại" của Gerard Meszaros.
adrianboimvaser

7

Miễn là kiểm tra đơn vị của bạn thực sự kiểm tra mã của bạn trong các trường hợp "nhất". (Nói nhiều nhất về mục đích vì đôi khi rất khó để tìm thấy tất cả các kết quả có thể). Tôi nghĩ mã "có mùi" là sở thích cá nhân của bạn. Tôi luôn viết mã theo cách tôi có thể đọc và hiểu nó trong vòng vài giây, thay vì đào bới rác và cố gắng hiểu cái gì là cái gì. Đặc biệt là khi bạn quay lại với nó sau một khoảng thời gian đáng kể.

Dòng dưới cùng - thử nghiệm của nó, nó giả sử là dễ dàng. Bạn không muốn nhầm lẫn với mã "có mùi".


5
+1: Không làm phiền mã kiểm tra đơn vị. Một số câu hỏi ngớ ngẩn nhất xoay quanh việc làm cho mã kiểm tra đơn vị trở nên "mạnh mẽ" hơn để thay đổi lập trình không phá vỡ bài kiểm tra đơn vị. Phần bên dưới. Các bài kiểm tra đơn vị được thiết kế để giòn. Không sao nếu chúng kém mạnh hơn mã ứng dụng mà chúng được thiết kế để kiểm tra.
S.Lott

1
@ S.Lott Cả hai đồng ý và không đồng ý, vì lý do tốt hơn giải thích trong câu trả lời của tôi.
Rein Henrichs

1
@Rein Henrichs: đó là những mùi xa, nghiêm trọng hơn nhiều so với mô tả trong câu hỏi. "Sao chép và dán" và "trông khá xấu xí" không có vẻ tệ như mùi của bạn mô tả trong đó các bài kiểm tra không đáng tin cậy.
S.Lott

1
@ S.Lott chính xác, tôi nghĩ rằng nếu chúng ta sẽ nói về "mùi thử nghiệm đơn vị" thì điều quan trọng là tạo nên sự khác biệt đó. Mã có mùi trong các bài kiểm tra đơn vị thường không. Chúng được viết cho các mục đích khác nhau và những căng thẳng làm cho chúng có mùi trong một bối cảnh rất khác nhau trong bối cảnh khác.
Rein Henrichs

2
@ S.Lott btw đây dường như là một cơ hội hoàn hảo để sử dụng tính năng trò chuyện bị bỏ quên nhiều :)
Rein Henrichs

6

Chắc chắn rồi. Một số người nói "bất kỳ bài kiểm tra nào tốt hơn là không có bài kiểm tra nào". Tôi hoàn toàn không đồng ý - các bài kiểm tra viết kém làm giảm thời gian phát triển của bạn và cuối cùng bạn sẽ lãng phí ngày sửa chữa các bài kiểm tra "bị hỏng" vì chúng không phải là bài kiểm tra đơn vị tốt ngay từ đầu. Đối với tôi tại thời điểm này, hai điều tôi đang tập trung để làm cho các bài kiểm tra của mình có giá trị, thay vì một gánh nặng, là:

Bảo trì

Bạn nên kiểm tra kết quả ( điều gì xảy ra), không phải phương thức ( cách nó xảy ra). Việc thiết lập thử nghiệm của bạn nên được tách rời khỏi quá trình thực hiện càng tốt: chỉ thiết lập kết quả cho các cuộc gọi dịch vụ, v.v ... thực sự cần thiết.

  • Sử dụng khung mô phỏng để đảm bảo các bài kiểm tra của bạn không phụ thuộc vào bất cứ điều gì bên ngoài
  • Ưu tiên sơ khai trên giả (nếu khung của bạn phân biệt giữa chúng) bất cứ khi nào có thể
  • Không có logic trong các bài kiểm tra! Ifs, switch, for-everyes, case, try-Catch, v.v ... đều là những no-nos lớn, vì chúng có thể đưa lỗi vào chính mã kiểm tra

Dễ đọc

Bạn có thể cho phép lặp lại nhiều hơn một chút trong các thử nghiệm của mình, điều mà bạn thường không cho phép trong mã sản xuất của mình, nếu điều đó làm cho chúng dễ đọc hơn. Chỉ cần cân bằng điều này với các công cụ bảo trì ở trên. Hãy rõ ràng trong những gì bài kiểm tra đang làm!

  • Cố gắng duy trì phong cách "sắp xếp, hành động, khẳng định" cho các bài kiểm tra của bạn. Điều này tách biệt thiết lập của bạn và kỳ vọng của kịch bản, từ hành động được thực hiện và kết quả được xác nhận.
  • Duy trì một xác nhận hợp lý cho mỗi bài kiểm tra (nếu tên bài kiểm tra của bạn có "và" trong đó, bạn có thể cần chia nó thành nhiều bài kiểm tra)

Tóm lại, bạn nên rất quan tâm đến các xét nghiệm "có mùi" - chúng có thể chỉ lãng phí thời gian của bạn, không mang lại giá trị.

Bạn đã nói:

Kiểm tra đơn vị thường yêu cầu các "hack có mùi" khác nhau như các chức năng khai thác.

Âm thanh như bạn chắc chắn có thể làm với việc đọc một số kỹ thuật Kiểm tra đơn vị, chẳng hạn như sử dụng khung Mocking, để làm cho cuộc sống của bạn trở nên dễ dàng hơn rất nhiều. Tôi rất rất muốn giới thiệu Nghệ thuật kiểm tra đơn vị , bao gồm những điều trên và nhiều hơn nữa. Tôi tìm thấy nó khai sáng sau khi vật lộn với các bài kiểm tra viết kém, không rõ ràng, "có mùi" trong một thời gian dài. Đó là một trong những khoản đầu tư thời gian tốt nhất mà tôi đã thực hiện trong năm nay!


Câu trả lời tuyệt vời. Tôi chỉ có một ngụy biện nhỏ: quan trọng hơn nhiều so với "một khẳng định logic trên mỗi bài kiểm tra" là một hành động cho mỗi bài kiểm tra. Vấn đề là cho dù có bao nhiêu bước để sắp xếp một thử nghiệm, thì cũng chỉ nên có một "hành động mã sản xuất được thử nghiệm". Nếu nói hành động nên có nhiều tác dụng phụ, bạn cũng có thể có nhiều xác nhận.
vỡ mộng

5

Hai câu hỏi cho bạn:

  • Bạn có hoàn toàn tích cực rằng bạn đang kiểm tra những gì bạn nghĩ rằng bạn đang kiểm tra?
  • Nếu ai đó nhìn vào bài kiểm tra đơn vị, liệu họ có thể tìm ra mã được cho là để làm gì không?

Có nhiều cách để xử lý các tác vụ lặp đi lặp lại trong các bài kiểm tra đơn vị của bạn, đó là cách thiết lập và phân tích mã phổ biến nhất. Về cơ bản, bạn có một phương pháp thiết lập thử nghiệm và phương pháp phá bỏ thử nghiệm - tất cả các khung thử nghiệm đơn vị đều hỗ trợ cho việc này.

Các bài kiểm tra đơn vị nên nhỏ và dễ hiểu. Nếu họ không và bài kiểm tra thất bại, làm thế nào bạn sẽ khắc phục vấn đề trong một khoảng thời gian hợp lý ngắn. Làm cho nó dễ dàng cho chính bạn trong một vài tháng khi bạn phải quay lại mã.


5

Khi thùng rác bắt đầu có mùi, đã đến lúc bỏ nó ra. Mã kiểm tra của bạn phải sạch như mã sản xuất của bạn. Bạn sẽ chỉ cho mẹ của bạn?


3

Ngoài các câu trả lời khác ở đây.

Mã chất lượng kém trong các bài kiểm tra đơn vị không bị giới hạn trong bộ kiểm tra đơn vị của bạn.

Một trong những vai trò được điền bởi Đơn vị kiểm tra là Tài liệu.

Bộ kiểm tra đơn vị là một trong những nơi mà người ta nhìn để tìm hiểu cách sử dụng API.

Người gọi API của bạn không thể sao chép các phần của bộ kiểm tra đơn vị của bạn, dẫn đến mã bộ kiểm thử xấu của bạn lây nhiễm mã trực tiếp ở nơi khác.


3

Tôi gần như không gửi câu trả lời của mình vì tôi mất một lúc để tìm ra cách tiếp cận vấn đề này như một câu hỏi hợp pháp.

Những lý do lập trình viên tham gia vào "thực tiễn tốt nhất" không phải vì lý do thẩm mỹ, hoặc vì họ muốn mã "hoàn hảo". Đó là bởi vì nó tiết kiệm thời gian cho họ.

  • Nó tiết kiệm thời gian vì mã tốt dễ đọc và dễ hiểu hơn.
  • Nó tiết kiệm thời gian vì khi bạn cần tìm một bản sửa lỗi, việc xác định vị trí sẽ dễ dàng và nhanh hơn.
  • Nó tiết kiệm thời gian vì khi bạn muốn mở rộng mã, việc đó dễ dàng hơn và nhanh hơn.

Vì vậy, câu hỏi mà bạn hỏi (theo quan điểm của tôi) là tôi nên tiết kiệm thời gian hay viết mã sẽ lãng phí thời gian của tôi?

Đối với câu hỏi đó tôi chỉ có thể nói, thời gian của bạn quan trọng như thế nào?

FYI: stubbing, mocking, và patch patch đều có công dụng hợp pháp. Họ chỉ "ngửi" khi sử dụng không phù hợp.


2

Tôi cố gắng đặc biệt để KHÔNG làm cho các bài kiểm tra đơn vị của tôi quá cướp. Tôi đã thấy các bài kiểm tra đơn vị bắt đầu thực hiện xử lý lỗi với tên là mạnh mẽ. Những gì bạn kết thúc là các bài kiểm tra nuốt chửng các lỗi mà họ đang cố gắng bắt. Kiểm tra đơn vị cũng phải làm một số điều thú vị khá thường xuyên để làm cho mọi thứ hoạt động. Hãy suy nghĩ về toàn bộ ý tưởng của những người truy cập riêng bằng cách sử dụng sự phản chiếu ... nếu tôi thấy một loạt những người trong mã sản xuất, tôi sẽ lo lắng 9 lần trong số 10. Tôi nghĩ nên dành nhiều thời gian hơn để suy nghĩ về những gì đang được thử nghiệm , thay vì sạch sẽ mã. Các bài kiểm tra sẽ cần phải được thay đổi khá thường xuyên nếu bạn thực hiện bất kỳ tái cấu trúc lớn nào, vậy tại sao không hack chúng lại với nhau, có ít cảm xúc sở hữu hơn và có động lực hơn để viết lại hoặc làm lại chúng khi đến lúc?


2

Nếu bạn định bảo hiểm nặng, mức độ thấp, bạn sẽ dành nhiều thời gian hoặc nhiều hơn cho mã kiểm tra như trong mã sản phẩm khi thực hiện bất kỳ sửa đổi nghiêm trọng nào.

Tùy thuộc vào độ phức tạp của thiết lập thử nghiệm, mã có thể phức tạp hơn. (httpcontext.c hiện tại so với con quái vật khủng khiếp cố gắng xây dựng một cái giả chính xác chẳng hạn)

Trừ khi sản phẩm của bạn là thứ mà bạn hiếm khi thay đổi giao diện hiện tại và các đầu vào cấp đơn vị của bạn rất đơn giản để thiết lập, tôi sẽ lo lắng về sự hiểu biết về các thử nghiệm như sản phẩm thực tế.


0

Mùi mã chỉ là một vấn đề trong mã khiến bạn cần phải thay đổi hoặc hiểu tại một thời điểm nào đó sau này.

Vì vậy, tôi nghĩ rằng bạn nên sửa mùi mã khi bạn phải "đóng" để kiểm tra đơn vị nhất định, nhưng không phải trước đó.

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.