Kiểm tra viết cho mã hiện có


68

Giả sử một người có một chương trình tương đối lớn (giả sử 900 nghìn SLOC trong C #), tất cả được nhận xét / ghi chép kỹ lưỡng, được tổ chức tốt và hoạt động tốt. Toàn bộ cơ sở mã được viết bởi một nhà phát triển cấp cao duy nhất không còn làm việc với công ty. Tất cả các mã đều có thể kiểm tra được và IoC được sử dụng xuyên suốt - ngoại trừ một số lý do kỳ lạ họ không viết bất kỳ bài kiểm tra đơn vị nào. Bây giờ, công ty của bạn muốn phân nhánh mã và muốn kiểm tra đơn vị được thêm vào để phát hiện khi thay đổi phá vỡ chức năng cốt lõi.

  • Là thêm kiểm tra là một ý tưởng tốt?
  • Nếu vậy, làm thế nào người ta thậm chí sẽ bắt đầu một cái gì đó như thế này?

BIÊN TẬP

OK, vì vậy tôi đã không mong đợi câu trả lời đưa ra lập luận tốt cho kết luận ngược lại. Vấn đề có thể nằm ngoài tầm tay của tôi. Tôi cũng đã đọc qua "các câu hỏi trùng lặp" và sự đồng thuận chung là "bài kiểm tra viết là tốt" ... vâng, nhưng không quá hữu ích trong trường hợp cụ thể này.

Tôi không nghĩ rằng tôi ở đây một mình trong việc suy ngẫm các bài kiểm tra viết cho một hệ thống cũ. Tôi sẽ giữ số liệu về thời gian sử dụng và số lần kiểm tra mới gặp sự cố (và số lần họ không thực hiện). Tôi sẽ quay lại và cập nhật điều này một năm hoặc lâu hơn với kết quả của tôi.

PHẦN KẾT LUẬN

Vì vậy, nó chỉ ra rằng về cơ bản là không thể chỉ thêm thử nghiệm đơn vị vào mã hiện có với bất kỳ ngữ nghĩa chính thống nào. Khi mã đang hoạt động, rõ ràng bạn không thể bật đèn đỏ / đèn xanh cho các thử nghiệm của mình, thường không rõ hành vi nào là quan trọng để kiểm tra, không rõ bắt đầu từ đâu và chắc chắn không rõ khi nào bạn kết thúc. Thực sự thậm chí hỏi câu hỏi này bỏ lỡ điểm chính của bài kiểm tra viết ở nơi đầu tiên. Trong phần lớn các trường hợp, tôi thấy việc viết lại mã bằng TDD thực sự dễ dàng hơn so với giải mã các hàm dự định và thêm hồi tố trong các bài kiểm tra đơn vị. Khi khắc phục sự cố hoặc thêm một tính năng mới, đó là một câu chuyện khác và tôi tin rằng đây là thời gian để thêm các bài kiểm tra đơn vị (như một số chỉ ra dưới đây). Cuối cùng, hầu hết các mã được viết lại, thường sớm hơn bạn mong đợi - thực hiện phương pháp này tôi '


10
Thêm kiểm tra sẽ không phá vỡ mã hiện có.
Dan Pichelman

30
@DanPichelman Bạn chưa bao giờ gặp phải lỗi schroedinorms - "Lỗi thiết kế hoặc triển khai trong chương trình không biểu hiện cho đến khi ai đó đọc nguồn hoặc sử dụng chương trình theo cách khác thường mà nó không bao giờ nên hoạt động, tại thời điểm đó chương trình kịp thời ngừng làm việc cho mọi người cho đến khi cố định. "

8
@MichaelT Bây giờ bạn đề cập đến nó, tôi nghĩ rằng tôi đã thấy một hoặc hai trong số đó. Nhận xét của tôi nên đọc "Thêm các bài kiểm tra thường sẽ không phá vỡ mã hiện có". Cảm ơn
Dan Pichelman

3
Chỉ viết các bài kiểm tra xung quanh những thứ mà bạn định tái cấu trúc hoặc thay đổi.
Steven Evers

3
Kiểm tra cuốn sách "Làm việc hiệu quả với Mã kế thừa": amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/ , Michael Feathers đề nghị viết các bài kiểm tra trước khi sửa đổi bất kỳ mã kế thừa nào.
Skarab

Câu trả lời:


68

Mặc dù các thử nghiệm là một ý tưởng tốt, ý định dành cho lập trình viên ban đầu là xây dựng chúng khi anh ta đang xây dựng ứng dụng để nắm bắt kiến ​​thức của mình về cách mã được sử dụng và những gì có thể bị phá vỡ, sau đó sẽ được chuyển cho bạn.

Khi thực hiện phương pháp này, có khả năng cao là bạn sẽ viết các bài kiểm tra ít có khả năng phá vỡ nhất và bỏ lỡ hầu hết các trường hợp cạnh sẽ được phát hiện trong khi xây dựng ứng dụng.

Vấn đề là hầu hết giá trị sẽ đến từ những 'vấn đề' và những tình huống ít rõ ràng hơn. Nếu không có các thử nghiệm đó, bộ thử nghiệm sẽ mất gần như toàn bộ hiệu quả của nó. Ngoài ra, công ty sẽ có một cảm giác an toàn sai lầm xung quanh ứng dụng của họ, vì nó sẽ không phải là bằng chứng hồi quy đáng kể hơn.

Thông thường, cách xử lý loại cơ sở mã này là viết các bài kiểm tra cho mã mới và cho việc tái cấu trúc mã cũ cho đến khi cơ sở mã cơ sở được tái cấu trúc hoàn toàn.

Cũng thấy .


11
Nhưng, ngay cả khi không có TDD, các bài kiểm tra đơn vị rất hữu ích khi tái cấu trúc.
pdr

1
Nếu mã tiếp tục hoạt động tốt, đó không phải là vấn đề, nhưng điều tốt nhất nên làm là kiểm tra giao diện với mã kế thừa bất cứ khi nào bạn viết bất cứ điều gì liên quan đến hành vi của nó.
deworde

1
Đây là lý do tại sao bạn đo lường phạm vi kiểm tra . Nếu thử nghiệm cho một phần cụ thể không bao gồm tất cả các if và elses và tất cả các trường hợp cạnh thì bạn không thể cấu trúc lại phần đó một cách an toàn. Bảo hiểm sẽ cho bạn biết nếu tất cả các dòng được nhấn để mục tiêu của bạn là tăng phạm vi bảo hiểm càng nhiều càng tốt trước khi tái cấu trúc.
Rudolf Olah

3
Một thiếu sót lớn của TDD là trong khi bộ phần mềm có thể chạy, đối với nhà phát triển không quen thuộc với cơ sở mã, đây là một cảm giác an toàn sai lầm. BDD tốt hơn nhiều về vấn đề này vì đầu ra là ý định của mã bằng tiếng Anh.
Robbie Dee

3
Cũng giống như đề cập rằng bảo hiểm mã 100% không có nghĩa là mã của bạn hoạt động chính xác 100%. Bạn có thể kiểm tra từng dòng mã cho phương thức nhưng chỉ vì nó hoạt động với value1 không có nghĩa là nó được đảm bảo hoạt động với value2.
ryanzec

35

Vâng, thêm các bài kiểm tra chắc chắn là một ý tưởng tốt.

Bạn nói rằng nó được ghi chép tốt, và điều đó đặt bạn vào một vị trí tốt. Hãy thử tạo các bài kiểm tra bằng cách sử dụng tài liệu đó làm hướng dẫn, tập trung vào các phần của hệ thống quan trọng hoặc có thể thay đổi thường xuyên.

Ban đầu, kích thước tuyệt đối của codebase có thể sẽ có vẻ áp đảo so với số lượng thử nghiệm nhỏ, nhưng không có cách tiếp cận lớn nào, và bắt đầu ở đâu đó quan trọng hơn là đau đớn về cách tiếp cận tốt nhất sẽ là gì.

Tôi muốn giới thiệu cuốn sách của Michael Feathers, Làm việc hiệu quả với Bộ luật kế thừa , để có một số lời khuyên chi tiết, tốt.


10
+1. Nếu bạn viết các bài kiểm tra dựa trên tài liệu, bạn sẽ phát hiện ra bất kỳ sự khác biệt nào giữa mã làm việc và tài liệu, và đó là vô giá.
Carl Manaster

1
Một lý do khác để thêm kiểm tra: khi tìm thấy lỗi, bạn có thể dễ dàng thêm trường hợp kiểm tra để kiểm tra hồi quy trong tương lai.

Chiến lược này về cơ bản là chiến lược được nêu trong khóa học trực tuyến edX (miễn phí) CS169.2x trong chương về mã kế thừa. Như các giáo viên nói: "Thiết lập thử nghiệm thực tế với các bài kiểm tra đặc tính" trong Chương 9 trong cuốn sách: beta.saasbook.info/table-of-contents
FGM

21

Không phải tất cả các bài kiểm tra đơn vị có lợi ích như nhau. Lợi ích của một bài kiểm tra đơn vị đến khi nó thất bại. Càng ít có khả năng thất bại, nó càng ít có lợi. Mã mới hoặc thay đổi gần đây có nhiều khả năng chứa lỗi hơn là mã hiếm khi được thay đổi được kiểm tra tốt trong sản xuất. Do đó, các thử nghiệm đơn vị trên mã mới hoặc thay đổi gần đây có nhiều khả năng có lợi hơn.

Không phải tất cả các bài kiểm tra đơn vị có chi phí như nhau. Việc kiểm tra mã tầm thường dễ dàng hơn nhiều mà bạn tự thiết kế ngày hôm nay so với mã phức tạp do người khác thiết kế từ lâu. Ngoài ra, kiểm tra trong quá trình phát triển thường tiết kiệm thời gian phát triển. Trên mã kế thừa mà tiết kiệm chi phí không còn nữa.

Trong một thế giới lý tưởng, bạn sẽ có tất cả thời gian bạn cần để kiểm tra mã kế thừa, nhưng trong thế giới thực, đến một lúc nào đó, lý do là chi phí của việc thêm các bài kiểm tra đơn vị vào mã kế thừa sẽ vượt trội hơn lợi ích. Bí quyết là xác định điểm đó. Kiểm soát phiên bản của bạn có thể giúp bằng cách hiển thị cho bạn mã được thay đổi gần đây nhất và được thay đổi thường xuyên nhất và bạn có thể bắt đầu bằng cách đặt các mã đó dưới dạng thử nghiệm đơn vị. Ngoài ra, khi bạn thực hiện các thay đổi trong tương lai, hãy đặt những thay đổi đó và mã liên quan chặt chẽ trong bài kiểm tra đơn vị.

Theo phương pháp đó, cuối cùng bạn sẽ có phạm vi bảo hiểm khá tốt trong các lĩnh vực có lợi nhất. Thay vào đó, nếu bạn dành hàng tháng để kiểm tra đơn vị tại chỗ trước khi tiếp tục các hoạt động tạo doanh thu, đó có thể là một quyết định bảo trì phần mềm mong muốn, nhưng đó là một quyết định kinh doanh tệ hại.


3
Nếu mã hiếm khi thất bại, rất nhiều thời gian và nỗ lực có thể được dành cho việc tìm kiếm các vấn đề phức tạp không bao giờ có thể xảy ra trong cuộc sống thực. Mặt khác, nếu mã bị lỗi và dễ bị lỗi, có lẽ bạn có thể bắt đầu thử nghiệm ở bất cứ đâu và tìm thấy sự cố ngay lập tức.
Robbie Dee

8

Là thêm kiểm tra là một ý tưởng tốt?

Hoàn toàn, mặc dù tôi thấy hơi khó tin rằng mã sạch và hoạt động tốt và sử dụng các kỹ thuật hiện đại và đơn giản là không có bài kiểm tra đơn vị. Bạn có chắc là họ không ngồi trong một giải pháp riêng biệt?

Dù sao, nếu bạn sẽ mở rộng / duy trì mã thì các bài kiểm tra đơn vị thực sự là vô giá đối với quy trình đó.

Nếu vậy, làm thế nào người ta thậm chí sẽ bắt đầu một cái gì đó như thế này?

Một bước tại một thời điểm. Nếu bạn không quen với thử nghiệm đơn vị, thì hãy tìm hiểu một chút. Khi bạn cảm thấy thoải mái với các khái niệm, chọn một phần nhỏ của mã và viết các bài kiểm tra cho nó. Sau đó, tiếp theo, và tiếp theo. Bảo hiểm mã có thể giúp bạn tìm thấy những điểm bạn đã bỏ lỡ.

Có lẽ tốt nhất là chọn những thứ nguy hiểm / rủi ro / quan trọng để kiểm tra trước, nhưng bạn có thể thử nghiệm hiệu quả hơn một cái gì đó thẳng tiến để đi vào rãnh trước - đặc biệt là nếu bạn / nhóm không quen với codebase và / hoặc đơn vị thử nghiệm.


7
"Bạn có chắc là họ không ngồi trong một giải pháp riêng biệt?" là một câu hỏi tuyệt vời Tôi hy vọng OP không bỏ qua nó.
Dan Pichelman

Không có cơ hội, ứng dụng đã được bắt đầu từ nhiều năm trước khi TDD đang đạt được lực kéo, vì vậy mục đích là để thử nghiệm tại một số điểm, nhưng vì một số lý do một khi dự án bắt đầu, họ không bao giờ có được nó.
Paul

2
Có lẽ họ không bao giờ có được điều đó bởi vì nó sẽ khiến họ mất thêm thời gian không đáng. Một nhà phát triển giỏi làm việc một mình chắc chắn có thể tạo ra một ứng dụng sạch, rõ ràng, được tổ chức tốt và hoạt động với kích thước tương đối lớn mà không cần bất kỳ kiểm tra tự động nào, và nói chung họ có thể làm điều đó nhanh hơn và không có lỗi như với các bài kiểm tra. Vì tất cả nằm trong đầu của họ, khả năng xảy ra lỗi hoặc sự cố tổ chức thấp hơn đáng kể so với trường hợp nhiều nhà phát triển tạo ra nó.
Ben Lee

3

Vâng, có bài kiểm tra là một ý tưởng tốt. Họ sẽ giúp ghi lại các cơ sở mã hiện tại hoạt động như dự định và nắm bắt mọi hành vi không mong muốn. Ngay cả khi các thử nghiệm ban đầu không thành công, hãy để chúng và sau đó cấu trúc lại mã sau để chúng vượt qua và hoạt động như dự định.

Bắt đầu viết bài kiểm tra cho các lớp nhỏ hơn (những lớp không có phụ thuộc và tương đối đơn giản) và chuyển sang các lớp lớn hơn (những lớp có phụ thuộc và phức tạp hơn). Sẽ mất nhiều thời gian, nhưng hãy kiên nhẫn và bền bỉ để cuối cùng bạn có thể bao quát được cơ sở mã càng nhiều càng tốt.


Bạn có thực sự thêm các bài kiểm tra thất bại vào một chương trình đang hoạt động tốt không (OP nói)?
MarkJ

Có, bởi vì nó cho thấy rằng một cái gì đó không hoạt động như dự định và yêu cầu xem xét thêm. Điều này sẽ nhắc nhở thảo luận và hy vọng sửa chữa bất kỳ sự hiểu lầm hoặc khiếm khuyết chưa biết trước đây.
Bernard

@Bernard - hoặc, các bài kiểm tra có thể phơi bày sự hiểu lầm của bạn về những gì mã được cho là phải làm. Các thử nghiệm được viết sau khi thực tế có nguy cơ không đóng gói chính xác các ý định ban đầu.
Dan Pichelman

@DanPichelman: Đồng ý, nhưng điều này không khuyến khích người ta viết bất kỳ bài kiểm tra nào cả.
Bernard

Nếu không có gì khác, nó sẽ chỉ ra rằng mã đã không được viết một cách phòng thủ.
Robbie Dee

3

OK, tôi sẽ đưa ra ý kiến ​​trái ngược ....

Việc thêm các bài kiểm tra vào một hệ thống đang hoạt động sẽ làm thay đổi hệ thống đó, trừ khi đó, tất cả đều được viết với ý định chế giễu ngay từ đầu. Tôi nghi ngờ điều đó, mặc dù hoàn toàn có khả năng nó có sự phân tách tốt tất cả các thành phần với các ranh giới dễ xác định mà bạn có thể trượt các giao diện giả của mình vào. Nhưng nếu không, thì bạn sẽ phải thực hiện những thay đổi khá quan trọng (nói tương đối) có thể phá vỡ mọi thứ. Trong trường hợp tốt nhất, bạn sẽ dành nhiều thời gian để viết các bài kiểm tra này, thời gian có thể tốt hơn để viết một tải tài liệu thiết kế chi tiết, tài liệu phân tích tác động hoặc tài liệu cấu hình giải pháp thay thế. Rốt cuộc, đó là công việc mà sếp của bạn muốn thực hiện nhiều hơn là kiểm tra đơn vị. Phải không?

Dù sao, tôi sẽ không thêm bất kỳ bài kiểm tra đơn vị nào.

Tôi sẽ tập trung vào các công cụ kiểm tra tự động bên ngoài sẽ cung cấp cho bạn phạm vi bảo hiểm hợp lý mà không thay đổi điều gì. Sau đó, khi bạn đến để thực hiện sửa đổi ... đó là khi bạn có thể bắt đầu thêm các bài kiểm tra đơn vị bên trong cơ sở mã.


2

Tôi thường gặp phải tình huống này, thừa hưởng một cơ sở mã lớn mà không có bảo hiểm đầy đủ hoặc không có kiểm tra, và bây giờ tôi chịu trách nhiệm thêm chức năng, sửa lỗi, v.v.

Lời khuyên của tôi là đảm bảo và kiểm tra những gì bạn thêm và nếu bạn sửa lỗi hoặc thay đổi các trường hợp sử dụng trong mã hiện tại, thì tác giả sẽ kiểm tra. Nếu bạn phải chạm vào một cái gì đó, viết bài kiểm tra tại thời điểm đó.

Khi điều này bị hỏng là khi mã hiện tại không được cấu trúc tốt để kiểm tra đơn vị, do đó bạn dành nhiều thời gian để tái cấu trúc để bạn có thể thêm các kiểm tra cho các thay đổi nhỏ.

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.