Khi nào thì thích hợp để không kiểm tra đơn vị?


138

Tôi làm việc trong một công ty nhỏ với tư cách là nhà phát triển solo. Tôi là nhà phát triển duy nhất tại công ty trên thực tế. Tôi có một số (tương đối) các dự án lớn tôi đã viết và duy trì thường xuyên, và không có dự án nào trong số chúng có các bài kiểm tra để hỗ trợ chúng. Khi tôi bắt đầu các dự án mới, tôi thường tự hỏi liệu tôi có nên thử một cách tiếp cận TDD không. Nghe có vẻ là một ý tưởng tốt, nhưng thật lòng tôi không bao giờ có thể biện minh cho công việc làm thêm có liên quan.

Tôi làm việc chăm chỉ để có tư duy cầu tiến trong thiết kế của mình. Tôi nhận ra rằng chắc chắn một ngày nào đó, một nhà phát triển khác sẽ phải duy trì mã của tôi hoặc ít nhất là khắc phục sự cố. Tôi giữ mọi thứ đơn giản nhất có thể và tôi nhận xét và ghi lại những điều khó nắm bắt. Và thực tế là những dự án này không quá lớn hoặc phức tạp đến nỗi một nhà phát triển đàng hoàng sẽ phải vật lộn để hiểu chúng.

Rất nhiều ví dụ mà tôi đã thấy về các bài kiểm tra đi vào chi tiết vụn vặt, bao gồm tất cả các khía cạnh của mã. Vì tôi là nhà phát triển duy nhất và tôi rất gần với mã trong toàn bộ dự án, nên việc theo mô hình kiểm tra viết thủ công sẽ hiệu quả hơn nhiều. Tôi cũng thấy các yêu cầu và tính năng thay đổi thường xuyên đủ để duy trì các bài kiểm tra sẽ thêm một lượng đáng kể lực kéo vào một dự án. Thời gian có thể được dành để giải quyết các nhu cầu kinh doanh.

Vì vậy, tôi kết thúc với cùng một kết luận mỗi lần. Lợi tức đầu tư quá thấp.

Thỉnh thoảng tôi đã thiết lập một vài thử nghiệm để đảm bảo tôi đã viết một thuật toán chính xác, như tính toán số năm mà một người nào đó đã ở công ty dựa trên ngày thuê của họ. Nhưng từ quan điểm bảo hiểm mã, tôi đã bao phủ khoảng 1% mã của mình.

Trong tình huống của tôi, bạn vẫn sẽ tìm cách biến đơn vị kiểm tra thành một thông lệ thường xuyên, hay tôi có lý khi tránh được chi phí đó không?

CẬP NHẬT: Một vài điều về tình huống của tôi mà tôi đã bỏ qua: Các dự án của tôi đều là các ứng dụng web. Để bao gồm tất cả mã của tôi, tôi phải sử dụng các kiểm tra giao diện người dùng tự động và đó là một lĩnh vực mà tôi vẫn không thấy lợi ích lớn so với kiểm tra thủ công.


1
Cảm ơn mọi người. Tôi đang học hỏi rất nhiều ở đây. Một vài điều về tình huống của tôi mà tôi đã bỏ qua: Các dự án của tôi đều là các ứng dụng web. Để bao gồm tất cả mã của tôi, tôi phải sử dụng các kiểm tra giao diện người dùng tự động và đó là một lĩnh vực mà tôi vẫn không thấy lợi ích lớn so với kiểm tra thủ công.
Ken Pespisa

1
Chúng tôi đang có thành công lớn tại Transactis bằng công cụ kiểm tra tự động hóa web của Telerik. Chúng tôi đã có hàng tá các thử nghiệm trình duyệt thủ công trước đây được chuyển đổi sang tự động hóa. Các bài kiểm tra tự động là CÁCH nhanh hơn và cũng TUYỆT VỜI để làm nổi bật bất kỳ vấn đề hiệu suất nào mà trang web của bạn có thể gặp phải.
John Kaster

2
Tôi đã thấy một dự án đã cố gắng kiểm tra trình duyệt tự động của các trang web hoàn chỉnh. Theo như tôi có thể nói, nó đã không tìm thấy bất kỳ lỗi nào trong số hàng trăm lỗi nghiêm trọng mà chúng tôi đã tìm thấy thông qua thử nghiệm thủ công và nó tốn rất nhiều thời gian để phát triển và duy trì. (Sử dụng Selen được điều khiển bởi NUnit). Tồi tệ hơn, một số bài kiểm tra thường xuyên bị hỏng do sự cố, do sự không tương thích của trình duyệt và khung kiểm tra.
O'Rooney

1
Đây thực sự không phải là một câu trả lời, chỉ là một quan sát ... lập luận của bạn chống lại kiểm thử đơn vị vì "các yêu cầu thay đổi quá thường xuyên" nhắc nhở tôi về lập luận ngược mà tôi nghe thấy khi tôi làm việc: "các chương trình của chúng tôi rất tĩnh, đó là điểm kiểm tra Nó? Nó gần như không bao giờ thay đổi! " ;)
Bane

2
Kiểm tra giao diện người dùng tự động của ứng dụng web không phải là kiểm tra đơn vị, chúng là một con thú hoàn toàn khác và tôi sẽ không trách bạn nếu bạn không muốn làm chúng. Nhưng tất cả mã doanh nghiệp của bạn phải ở trong phần phụ trợ và đó là những gì bạn nên kiểm tra.
Nyamiou The Galeanthrope

Câu trả lời:


84

Rất nhiều ví dụ mà tôi đã thấy về các bài kiểm tra đi vào chi tiết vụn vặt, bao gồm tất cả các khía cạnh của mã.

Vì thế? Bạn không phải kiểm tra mọi thứ . Chỉ là những điều có liên quan.

Vì tôi là nhà phát triển duy nhất và tôi rất gần với mã trong toàn bộ dự án, nên việc theo mô hình kiểm tra viết thủ công sẽ hiệu quả hơn nhiều.

Điều đó thực sự sai. Nó không hiệu quả hơn. Đó thực sự chỉ là một thói quen.

Những gì các nhà phát triển solo khác làm là viết một bản phác thảo hoặc phác thảo, viết các trường hợp thử nghiệm và sau đó điền vào bản phác thảo với mã cuối cùng.

Điều đó rất, rất hiệu quả.

Tôi cũng thấy các yêu cầu và tính năng thay đổi thường xuyên đủ để duy trì các bài kiểm tra sẽ thêm một lượng đáng kể lực kéo vào một dự án.

Điều đó cũng sai. Các bài kiểm tra không phải là lực cản. Các yêu cầu thay đổi là kéo.

Bạn phải sửa các bài kiểm tra để phản ánh các yêu cầu. Cho dù chi tiết vụn vặt của họ, hoặc cấp cao; viết đầu tiên hoặc viết cuối cùng.

Mã không được thực hiện cho đến khi các bài kiểm tra vượt qua. Đó là một sự thật phổ biến của phần mềm.

Bạn có thể có một bài kiểm tra chấp nhận "ở đây là" giới hạn.

Hoặc bạn có thể có một số bài kiểm tra đơn vị.

Hoặc bạn có thể có cả hai.

Nhưng bất kể bạn làm gì, luôn có một thử nghiệm để chứng minh rằng phần mềm hoạt động.

Tôi muốn đề xuất rằng một chút về hình thức và bộ công cụ kiểm tra đơn vị đẹp sẽ làm cho bài kiểm tra đó hữu ích hơn rất nhiều.


8
Tôi thích tuyên bố đầu tiên của bạn, để chỉ kiểm tra những điều có liên quan. Về hiệu quả của kiểm tra thủ công so với kiểm tra đơn vị, tôi không tin rằng tuyên bố của tôi là hoàn toàn sai, cũng không phải của bạn là hoàn toàn đúng. Có vẻ như có sự cân bằng giữa thử nghiệm tự động và thủ công để đạt được hiệu quả tối đa.
Ken Pespisa

9
@Ken Pespisa: Xin lỗi. Tôi đã uống TDD Kool-Aid khoảng hai năm trước (sau 30 năm thử nghiệm cuối cùng). Bây giờ tôi bị kẹt trong bài kiểm tra đầu tiên. Nó làm cho tôi nhiều, năng suất hơn nhiều vì tôi ít suy nghĩ phải làm khi xây dựng.
S.Lott

3
@Ken Pespisa: Không. Có sự cân bằng trong các câu trả lời. Nếu bạn hỏi liệu có đúng không khi chia cho 0, bạn sẽ nhận được câu trả lời áp đảo nghiêng về một lý do. Nếu bạn hỏi có sqrt(-1)nên là số nguyên không, bạn sẽ nhận được câu trả lời áp đảo nghiêng về một chiều. Sự cân bằng là xung quanh "làm thế nào" và "thứ tự". Thực tế là bạn phải kiểm tra. Vì vậy, viết các bài kiểm tra đầu tiên và chắc chắn rằng chúng làm việc.
S.Lott

21
Xem xét đơn vị kiểm tra giao diện không phải là chi tiết thực hiện. Kiểm tra các giới hạn và trường hợp biên giới. Kiểm tra mã rủi ro. Rất nhiều mã đủ đơn giản để xác minh bằng cách kiểm tra, mặc dù việc kiểm tra mã của bạn dễ bị lỗi hơn là kiểm tra mã của người khác. Lần kiểm tra thủ công lần đầu tiên có thể hiệu quả hơn, bởi lần kiểm tra tự động lần thứ mười đang đi trước.
BillThor

10
"Mã không được thực hiện cho đến khi các bài kiểm tra vượt qua" - Không thực sự, IMO. Mã bắt đầu khi nó vượt qua các bài kiểm tra. Mã không được thực hiện cho đến khi nó tồn tại được một hoặc hai năm và phải chịu các bài kiểm tra căng thẳng và kiểm tra tích hợp với cơ sở người dùng lớn, tích cực và thiếu kiên nhẫn. Đó là thử nghiệm duy nhất thực sự được tính.
Vector

107

Hãy tưởng tượng rằng bạn có một bộ các bài kiểm tra có thể chạy trong một liên kết mắt và sẽ sáng lên một ánh sáng màu lục hoặc đỏ. Hãy tưởng tượng rằng bộ thử nghiệm này đã thử nghiệm mọi thứ ! Hãy tưởng tượng rằng tất cả những gì bạn phải làm để chạy bộ thử nghiệm là gõ ^ T. Sức mạnh này sẽ cung cấp cho bạn?

Bạn có thể thay đổi mã mà không sợ phá vỡ một cái gì đó? Bạn có thể thêm một tính năng mới mà không sợ phá vỡ một tính năng cũ? Bạn có thể dọn dẹp mã lộn xộn một cách nhanh chóng mà không sợ làm hỏng?

Vâng, bạn có thể làm tất cả những điều đó! Và điều gì sẽ xảy ra với mã của bạn theo thời gian? Nó sẽ ngày càng sạch hơn vì sẽ không có rủi ro để làm sạch nó.

Hãy tưởng tượng rằng bạn có một nàng tiên nhỏ trên vai. Mỗi khi bạn viết một dòng mã, nàng tiên sẽ thêm một cái gì đó vào bộ kiểm tra đã kiểm tra rằng dòng mã đó đã làm những gì nó dự định làm. Vì vậy, cứ sau vài giây bạn có thể nhấn ^ T và thấy rằng dòng mã cuối cùng bạn viết đã hoạt động.

Bạn nghĩ bạn sẽ làm được bao nhiêu việc sửa lỗi?

Nếu điều này nghe giống như tưởng tượng, bạn đã đúng. Nhưng thực tế không khác nhiều. Thay thế nhãn cầu bằng một vài giây và bà tiên bằng kỷ luật TDD, và bạn đã có khá nhiều thứ.

Giả sử bạn đang quay trở lại một hệ thống mà bạn đã xây dựng một năm trước và bạn đã quên cách tạo một trong những đối tượng trung tâm. Có những thử nghiệm tạo ra đối tượng đó theo mọi cách nó có thể được tạo ra. Bạn có thể đọc những bài kiểm tra và chạy bộ nhớ của bạn. Cần gọi API? Có những bài kiểm tra gọi API đó theo mọi cách có thể được gọi. Những bài kiểm tra này là những tài liệu nhỏ , được viết bằng ngôn ngữ mà bạn hiểu. Họ hoàn toàn không mơ hồ. Họ chính thức đến mức họ thi hành. Và họ không thể đồng bộ với ứng dụng!

Không đáng để đầu tư? Bạn trêu tôi! Làm thế nào bất cứ ai KHÔNG muốn bộ thử nghiệm đó? Làm cho mình một ưu tiên và ngừng ngụy biện cho silliness. Học cách làm TDD tốt và xem bạn đi nhanh hơn bao nhiêu và mã của bạn sạch hơn bao nhiêu.


28
Ái chà, chú Bob? Thật tuyệt khi có được suy nghĩ của bạn ở đây. Tôi đồng ý với bạn về lợi ích của TDD, thực sự không có đối số để có ở đó. Câu hỏi là về đầu tư thời gian và ROI. Nó không ngớ ngẩn đối với tôi để xem xét những điều này. Hãy tưởng tượng một dự án sẽ khiến tôi mất 50% thời gian để hoàn thành với TDD hơn là không có, và bà tiên nói với tôi rằng nó sẽ chỉ giúp tôi tiết kiệm 10% thời gian so với thử nghiệm thủ công trong suốt vòng đời của dự án. Điều đó có vẻ như là một tưởng tượng, nhưng tôi thấy nó hoàn toàn hợp lý với một số dự án nhất định.
Ken Pespisa

11
@Ken "Hãy tưởng tượng một dự án sẽ khiến tôi mất thêm 50% thời gian để hoàn thành với TDD hơn là không có". Nghe có vẻ chính xác như tưởng tượng với tôi. Trong thực tế, có vẻ như bạn chỉ cần đưa ra con số đó ngay tại chỗ mà không có bằng chứng để hỗ trợ nó.
Rein Henrichs

18
@Rein Henrichs - Tất nhiên tôi đã đưa ra con số, đó là một tuyên bố giả thuyết. Tôi đang đưa ra quan điểm rằng TDD bổ sung một lượng thời gian đáng kể cho một dự án và tôi phải xem xét liệu tôi sẽ nhận được một cái gì đó có giá trị tương đương hoặc tốt hơn. Bạn không cần phải thuyết phục tôi về các giá trị của TDD, tôi đã bị thuyết phục. Nhưng nó không phải là thuốc chữa bách bệnh.
Ken Pespisa

11
@Rein, chính xác thì "bằng chứng có sẵn là gì?" Xin hãy giải thích.
Ken Pespisa

22
@Uncle Bob "Thay thế nhãn cầu bằng vài giây": Tất nhiên là bạn đang nói đùa. TDD là một công cụ tốt, nhưng bạn chỉ phải kiểm tra các phần có liên quan nếu không bạn dành nhiều thời gian để duy trì các bài kiểm tra hơn là thực hiện bất kỳ sự phát triển nghiêm túc nào. Điều này đặc biệt đúng khi các yêu cầu thay đổi rất nhanh: bạn liên tục viết và vứt bỏ các bài kiểm tra cho các lớp thay đổi mọi lúc. Tôi không nói TDD là xấu, nó phải được sử dụng hợp lý và không được áp dụng một cách máy móc như bạn có vẻ đề nghị.
Giorgio

34

Sai lầm bạn đang mắc phải là bạn đang xem thử nghiệm như một khoản đầu tư thời gian mà không có lợi nhuận ngay lập tức. Nó không nhất thiết phải làm việc như vậy.

Đầu tiên các bài kiểm tra viết thực sự tập trung vào bạn về phần mà mã này cần làm.

Thứ hai chạy chúng cho thấy các lỗi sẽ xuất hiện trong thử nghiệm.

Thứ ba chạy chúng đôi khi xuất hiện các lỗi mà nếu không sẽ xuất hiện trong thử nghiệm và sau đó sẽ thực sự cắn bạn trong sản xuất.

Thứ tư, nếu bạn gặp lỗi với một hệ thống đang chạy và tạo một bài kiểm tra đơn vị cho nó, bạn sẽ không thể giới thiệu lại lỗi đó sau. Đó có thể là một trợ giúp thực sự lớn. Lỗi giới thiệu lại là phổ biến và rất khó chịu.

Thứ năm, nếu bạn cần trao mã cho người khác, một bộ kiểm tra sẽ giúp cuộc sống của họ dễ dàng hơn rất nhiều. Ngoài ra nếu bạn đã bỏ qua một dự án và quay lại với nó sau một vài năm, bạn sẽ không còn thân thiết với nó nữa và nó cũng sẽ hữu ích cho bạn.

Kinh nghiệm của tôi đã luôn luôn là trong suốt quá trình phát triển của một dự án, có các bài kiểm tra đơn vị đàng hoàng luôn làm cho quá trình nhanh hơn và đáng tin cậy hơn.


2
@Ken, bộ kiểm tra là thông số kỹ thuật ở dạng thực thi.

32

Những người trong JUnit (khung kiểm tra Đơn vị Java) có một triết lý rằng nếu quá đơn giản để kiểm tra, đừng kiểm tra nó . Tôi đặc biệt khuyên bạn nên đọc Câu hỏi thường gặp về Thực tiễn Tốt nhất của họ , vì nó khá thực dụng.

TDD là một quá trình khác nhau để viết phần mềm của bạn. Tiền đề cơ bản đằng sau kiểm thử đơn vị là bạn sẽ dành ít thời gian hơn cho trình gỡ lỗi bước qua mã và nhanh chóng tìm ra nếu thay đổi mã của bạn vô tình phá vỡ một thứ khác trong hệ thống. Điều đó phù hợp với TDD. Chu trình TDD là như thế này:

  1. Viết một bài kiểm tra
  2. Xem nó thất bại (chứng minh bạn có việc phải làm)
  3. Chỉ viết những gì cần thiết để vượt qua bài kiểm tra - không còn nữa.
  4. Xem nó qua (yay!)
  5. Refactor (làm cho nó tốt hơn)
  6. Rửa, rửa và lặp lại

Điều ít rõ ràng hơn khi áp dụng TDD là nó thay đổi cách viết mã của bạn . Bằng cách buộc bản thân suy nghĩ về cách kiểm tra / xác nhận rằng mã đang hoạt động, bạn đang viết mã kiểm tra. Và vì chúng ta đang nói về thử nghiệm đơn vị, điều đó thường có nghĩa là mã của bạn trở nên mô đun hơn. Đối với tôi, mã mô-đun và thử nghiệm là một chiến thắng lớn lên phía trước.

Bây giờ, bạn có cần kiểm tra những thứ như thuộc tính C # không? Hãy tưởng tượng một tài sản được định nghĩa như thế này:

bool IsWorthTesting {get; set;}

Câu trả lời sẽ là "không" không đáng để thử nghiệm, vì tại thời điểm này, bạn đang thử nghiệm tính năng ngôn ngữ. Chỉ cần tin tưởng rằng các chàng trai nền tảng C # đã làm đúng. Bên cạnh đó, nếu nó thất bại, bạn có thể làm gì để khắc phục nó?

Ngoài ra, bạn sẽ thấy rằng có một số phần nhất định trong mã của bạn sẽ rất nỗ lực để kiểm tra đúng cách. Điều đó có nghĩa là không làm điều đó, nhưng hãy đảm bảo bạn kiểm tra mã sử dụng / được sử dụng bởi vấn đề khó khăn:

  • Đã kiểm tra các ngoại lệ chỉ có thể xảy ra nếu cài đặt bị lỗi. Java có rất nhiều trong số này. Bạn được yêu cầu viết một khối bắt hoặc khai báo ngoại lệ được kiểm tra ngay cả khi không có cách nào nó có thể thất bại mà không hack các tệp đã cài đặt.
  • Giao diện người dùng. Việc tìm kiếm sự kiểm soát đang được thử nghiệm và gọi ra các sự kiện phù hợp để mô phỏng hành động của người dùng là rất rắc rối và trong một số trường hợp là không thể. Tuy nhiên, nếu bạn sử dụng mẫu Model / View / Controller, bạn có thể chắc chắn rằng model và bộ điều khiển của bạn đã được kiểm tra và để phần xem để kiểm tra thủ công.
  • Tương tác máy khách / máy chủ. Đây không còn là một bài kiểm tra đơn vị, và bây giờ là một bài kiểm tra tích hợp . Viết tất cả các phần đi đến gửi và nhận tin nhắn qua dây, nhưng không thực sự đi qua dây. Một cách tiếp cận tốt là giảm trách nhiệm của mã thực sự nói chuyện qua dây với truyền thông thô. Trong mã kiểm tra đơn vị của bạn, giả lập đối tượng giao tiếp để đảm bảo các dịch vụ đang hoạt động như bạn mong đợi.

Dù bạn có tin hay không, TDD sẽ giúp bạn rơi vào một tốc độ phát triển bền vững. Không phải vì phép thuật, mà là vì bạn có một vòng phản hồi chặt chẽ và bạn có thể nhanh chóng bắt được những sai lầm ngớ ngẩn. Chi phí sửa chữa những sai lầm đó về cơ bản là không đổi (ít nhất là đủ cho mục đích lập kế hoạch) bởi vì những sai lầm nhỏ không bao giờ lớn lên thành những sai lầm lớn. So sánh điều đó với bản chất bùng nổ của các lần chạy nước rút mã binge / debug.


24

Bạn phải cân bằng chi phí kiểm tra với chi phí lỗi.

Viết một bài kiểm tra đơn vị 10 dòng cho một chức năng mở một tệp, trong đó lỗi là "không tìm thấy tệp" là vô nghĩa.

Một hàm thực hiện một cái gì đó phức tạp đối với cấu trúc dữ liệu phức tạp - thì rõ ràng là có.

Các bit khéo léo là ở giữa. Nhưng hãy nhớ giá trị thực của các bài kiểm tra đơn vị không kiểm tra chức năng cụ thể, đó là kiểm tra các tương tác phức tạp giữa chúng. Vì vậy, một bài kiểm tra đơn vị phát hiện ra rằng một thay đổi trong một bit mã, phá vỡ một số chức năng trong một mô-đun khác cách đó 1000 dòng, có giá trị trọng lượng của nó trong cà phê.


23

Kiểm tra là đánh bạc.

Tạo một thử nghiệm là đặt cược rằng chi phí lỗi trong một đơn vị xảy ra và không bắt chúng với thử nghiệm đó (hiện tại và trong tất cả các lần sửa đổi mã trong tương lai) lớn hơn chi phí phát triển thử nghiệm. Những chi phí phát triển thử nghiệm này bao gồm những thứ như bảng lương cho kỹ thuật thử nghiệm bổ sung, thêm thời gian vào thị trường, chi phí cơ hội bị mất từ ​​việc không mã hóa các thứ khác, v.v.

Giống như bất kỳ đặt cược nào, đôi khi bạn thắng, đôi khi bạn thua.

Đôi khi phần mềm muộn với ít lỗi hơn sẽ chiến thắng các công cụ nhanh nhưng có lỗi được đưa ra thị trường trước. Đôi khi ngược lại. Bạn phải xem số liệu thống kê trong lĩnh vực cụ thể của mình và quản lý muốn đánh bạc bao nhiêu.

Một số loại lỗi có thể rất khó được thực hiện hoặc loại bỏ khỏi bất kỳ thử nghiệm độ tỉnh sớm nào, vì theo thống kê không đáng để dành thời gian để tạo thêm các xét nghiệm cụ thể. Nhưng đôi khi chi phí của một lỗi quá lớn (y tế, hạt nhân, v.v.) đến nỗi một công ty phải đặt cược thua lỗ (tương tự như mua bảo hiểm). Nhiều ứng dụng không có chi phí thất bại cao như vậy và do đó không cần bảo hiểm kinh tế cao hơn. Những người khác làm.


3
Câu trả lời tốt. Một trong số ít đó thực sự trả lời câu hỏi ban đầu của tôi. Tôi đã chìm trong thế giới thử nghiệm kể từ khi viết bài đăng này (tôi thích nó btw.) Tôi cần hiểu nó nhiều hơn trước khi tôi thực sự có thể biết khi nào nên sử dụng nó (hoặc không). Vì nhiều lý do đã nêu ở đây, tôi thích sử dụng nó mọi lúc. Nhưng cuối cùng nó sẽ phụ thuộc vào mức độ tôi nhận được nhanh hơn bao nhiêu, vì cuối cùng, đó là một canh bạc thời gian của tôi, nằm dưới sự kiểm soát của công ty / khách hàng của tôi và họ thường tập trung vào các góc dưới cùng của tam giác dự án: vi. wikipedia.org/wiki/Project_trigin
Ken Pespisa

10

Lời khuyên của tôi là chỉ kiểm tra mã mà bạn muốn làm việc đúng.

Đừng kiểm tra mã mà bạn muốn bị lỗi và gây ra sự cố cho bạn.


9
Nhắc nhở tôi về câu nói mà nha sĩ của tôi có: Bạn không cần phải xỉa răng, chỉ là những cái bạn muốn giữ.
Ken Pespisa

Tôi thú nhận đó là những gì làm tôi nghĩ về nó. ;-)
Nick Hodges

8

Tôi thường tự hỏi liệu tôi có nên thử một cách tiếp cận TDD. Nghe có vẻ là một ý tưởng tốt, nhưng thật lòng tôi không bao giờ có thể biện minh cho công việc làm thêm có liên quan.

TDD và Kiểm tra đơn vị không giống nhau.

Bạn có thể viết mã, sau đó thêm các bài kiểm tra đơn vị sau. Đó không phải là TDD, và rất nhiều công việc làm thêm.

TDD là thực hành mã hóa trong một vòng lặp của Red Light. Đèn xanh. Lặp lại cấu trúc lại.

Điều này có nghĩa là viết các bài kiểm tra cho mã chưa tồn tại, xem các bài kiểm tra thất bại, sửa mã để làm cho các bài kiểm tra hoạt động, sau đó làm cho mã "đúng". Điều này thường giúp bạn tiết kiệm công việc

Một trong những lợi thế của TDD là nó làm giảm nhu cầu suy nghĩ về những chuyện vặt vãnh. Những thứ như lỗi off-by-one biến mất. Bạn không cần phải tìm kiếm tài liệu API để tìm hiểu xem danh sách mà nó trả về bắt đầu từ 0 hay 1, chỉ cần làm điều đó.


Bạn có thể giải thích làm thế nào các lỗi off-by-one biến mất? Bạn đang nói rằng bạn có thể nhanh chóng nhận được câu trả lời của mình về việc liệu chỉ mục của một mảng là dựa trên không hay dựa trên một thử nghiệm hơn là tìm kiếm thông qua tài liệu? Có vẻ như không thể với tôi - Tôi khá nhanh trên Google :)
Ken Pespisa

1
Trên thực tế, viết TDD là một cách tuyệt vời để khám phá API (bao gồm một cơ sở mã kế thừa, cho mục đích ghi lại chức năng).
Frank Shearar

Nó cũng rất hữu ích nếu API đó thay đổi ... Bạn đột nhiên có một số thử nghiệm thất bại :-)
bitsoflogic

@Ken Pespisa, Nó chắc chắn nhanh hơn - viết mã dựa trên việc bạn nghĩ nó là 0 hay 1, chạy nó, sửa nó nếu cần. Hầu hết thời gian, bạn sẽ đúng và bạn đã bỏ qua việc phải tìm kiếm nó, nếu bạn sai, bạn biết trong vòng 10 giây.
Paul Butcher

Lợi ích rất thú vị. Tôi khá thích thứ đó.
Ken Pespisa

3

Tôi đã làm việc trên một hệ thống mà chúng tôi đã thử nghiệm hầu hết mọi thứ. Các thực thi đáng chú ý để kiểm tra là mã đầu ra PDF và XLS.

Tại sao? Chúng tôi có thể kiểm tra các phần thu thập dữ liệu và xây dựng mô hình được sử dụng để tạo đầu ra. Chúng tôi cũng có thể kiểm tra các phần đã tìm ra phần nào của mô hình sẽ chuyển đến các tệp PDF. Chúng tôi không thể kiểm tra xem PDF có ổn không vì điều đó hoàn toàn chủ quan. Chúng tôi không thể kiểm tra rằng tất cả các phần trong tệp PDF có thể đọc được đối với người dùng thông thường vì đó cũng là chủ quan. Hoặc nếu sự lựa chọn giữa biểu đồ thanh và bánh là chính xác cho tập dữ liệu.

Nếu đầu ra sẽ chủ quan, có rất ít thử nghiệm đơn vị bạn có thể làm những gì xứng đáng với nỗ lực.


Trên thực tế, loại thử nghiệm này có lẽ là "thử nghiệm tích hợp". Và vâng, kiểm thử tích hợp khó hơn nhiều so với kiểm thử đơn vị, và một lý do là đôi khi các quy tắc cho những gì "chính xác" rất phức tạp, hoặc thậm chí chủ quan.
sleske

2

Đối với nhiều thứ, một 'kiểm tra viết rồi viết thủ công' không mất nhiều thời gian hơn so với viết một vài bài kiểm tra. Tiết kiệm thời gian đến từ việc có thể chạy lại các bài kiểm tra đó bất cứ lúc nào.

Nghĩ về nó: Nếu bạn có một số tính năng bảo hiểm đàng hoàng với các bài kiểm tra của bạn (không nên nhầm lẫn với mã số bảo hiểm), và giả sử bạn có 10 tính năng - nhấp chuột vào một nút có nghĩa là bạn có khoảng 10 yous lại làm các xét nghiệm của bạn ... trong khi bạn ngồi lại và nhâm nhi cà phê

Bạn cũng không phải kiểm tra minutae. Bạn có thể viết các bài kiểm tra tích hợp bao gồm các tính năng của bạn nếu bạn không muốn tìm hiểu chi tiết về sự bẩn thỉu ... IMO, một số bài kiểm tra đơn vị có thể kiểm tra ngôn ngữ và nền tảng quá tốt, chứ không phải mã.

TL; DR Thật sự không bao giờ phù hợp vì lợi ích quá tốt.


2

Hai câu trả lời rất hay mà tôi đã gặp ở đây:

  1. Khi nào kiểm tra đơn vị so với kiểm tra thủ công
  2. Điều gì không kiểm tra khi nói đến Đơn vị kiểm tra?

Các biện minh cho việc tránh chi phí nhận thức:

  • Thời gian ngay lập tức / Tiết kiệm chi phí cho công ty của bạn
  • Thời gian tiềm năng / tiết kiệm chi phí trong khắc phục sự cố / bảo trì / gia hạn trong thời gian dài ngay cả khi bạn đã đi.

Bạn sẽ không muốn để lại một sản phẩm tuyệt vời từ phía bạn như là bằng chứng về chất lượng công việc của bạn? Nói theo cách ích kỷ, nó không tốt hơn cho bạn mà bạn làm?


1
Câu hỏi hay ở cuối Tôi tự hào về công việc của mình, hoàn toàn, và các ứng dụng của tôi hoạt động rất tốt (nếu tôi có thể quá táo bạo). Nhưng bạn đã đúng - họ thậm chí có thể tốt hơn với sự hỗ trợ của một số bài kiểm tra. Tôi nghĩ rằng việc tôi bỏ đi ở đây là cố gắng phù hợp với càng nhiều thử nghiệm hữu ích càng tốt trong thời gian tôi phải làm việc trong dự án và không bị ám ảnh về phạm vi bảo hiểm mã.
Ken Pespisa

1

Các nhà phát triển chuyên nghiệp viết các bài kiểm tra đơn vị bởi vì, về lâu dài, họ tiết kiệm thời gian. Bạn sẽ kiểm tra mã của mình sớm hay muộn, và nếu bạn không sử dụng, và nếu bạn phải sửa lỗi sau này, họ sẽ khó sửa hơn và có nhiều hiệu ứng hơn.

Nếu bạn đang viết mã không có bài kiểm tra và không có lỗi thì tốt. Tôi không tin rằng bạn có thể viết một hệ thống không tầm thường với các lỗi không, vì vậy tôi cho rằng bạn đang thử nghiệm nó bằng cách này hay cách khác.

Kiểm tra đơn vị cũng rất quan trọng để ngăn hồi quy khi bạn sửa đổi hoặc cấu trúc lại mã cũ. Họ không chứng minh sự thay đổi của bạn đã không phá vỡ mã cũ nhưng họ cho bạn rất nhiều sự tự tin (miễn là họ vượt qua tất nhiên :))

Tôi sẽ không quay lại và viết cả loạt bài kiểm tra cho mã mà bạn đã gửi, nhưng lần sau bạn cần sửa đổi một tính năng tôi khuyên bạn nên thử viết bài kiểm tra cho mô-đun hoặc lớp đó, hãy nhận mức độ bao phủ của bạn lên tới 70% + trước khi bạn áp dụng bất kỳ thay đổi. Xem nếu nó giúp bạn.

Nếu bạn thử nó và có thể thành thật nói rằng nó không có ích gì thì đủ công bằng, nhưng tôi nghĩ có đủ bằng chứng trong ngành rằng họ sẽ giúp nó ít nhất xứng đáng với bạn trong khi thử nghiệm phương pháp này.


Tôi thích những suy nghĩ về việc ngăn chặn hồi quy và thêm tự tin. Đó chính xác là những lý do tôi muốn thêm các bài kiểm tra.
Ken Pespisa

1

Có vẻ như hầu hết các câu trả lời là pro-TDD, mặc dù câu hỏi không hỏi về TDD nhưng về các bài kiểm tra đơn vị nói chung.

Không có một quy tắc hoàn toàn khách quan nào đằng sau những gì để kiểm tra đơn vị hay không kiểm tra đơn vị. Nhưng có một vài lần mà dường như nhiều lập trình viên không kiểm tra đơn vị:

  1. Phương pháp riêng tư

Tùy thuộc vào triết lý OOP của bạn, bạn có thể tạo các phương thức riêng tư để tách các thói quen phức tạp khỏi các phương thức công khai của bạn. Các phương thức công khai thường được gọi ở nhiều nơi khác nhau và được sử dụng thường xuyên, và các phương thức riêng chỉ thực sự được gọi bằng một hoặc hai phương thức công khai trong một lớp hoặc mô-đun để một cái gì đó rất cụ thể. Nó thường là đủ để viết các bài kiểm tra đơn vị cho các phương thức công khai nhưng không phải là các phương thức riêng tư tiềm ẩn làm cho một số phép thuật xảy ra. Nếu có sự cố xảy ra với một phương thức riêng tư, các thử nghiệm đơn vị phương thức công khai của bạn sẽ đủ tốt để phát hiện các vấn đề này.

  1. Những điều bạn đã biết nên hoạt động (hoặc những thứ được kiểm tra bởi người khác)

Rất nhiều lập trình viên mới chống lại điều này khi họ lần đầu tiên học kiểm tra và nghĩ rằng họ cần kiểm tra từng dòng được thực thi. Nếu bạn đang sử dụng một thư viện bên ngoài và chức năng của nó được kiểm tra và ghi lại tốt bởi các tác giả của nó, thì thường sẽ vô nghĩa khi kiểm tra chức năng cụ thể trong các bài kiểm tra đơn vị. Ví dụ: ai đó có thể viết một bài kiểm tra để đảm bảo rằng mô hình ActiveRecord của họ vẫn duy trì giá trị chính xác cho một thuộc tính với hàm gọi lại "before_save" vào cơ sở dữ liệu, mặc dù chính hành vi đó đã được kiểm tra kỹ lưỡng trong Rails. Các phương thức mà cuộc gọi lại đang gọi, có lẽ, nhưng không phải chính hành vi gọi lại. Bất kỳ vấn đề tiềm ẩn nào với các thư viện nhập khẩu sẽ được tiết lộ tốt hơn thông qua các thử nghiệm chấp nhận, thay vì các thử nghiệm đơn vị.

Cả hai đều có thể áp dụng cho dù bạn đang làm TDD hay không.


0

Ken, tôi và nhiều nhà phát triển khác ngoài kia đã đi đến kết luận giống như bạn nhiều lần trong suốt sự nghiệp của chúng tôi.

Sự thật mà tôi tin rằng bạn sẽ tìm thấy (cũng như nhiều người khác) là việc đầu tư ban đầu cho các bài kiểm tra viết cho ứng dụng của bạn có vẻ khó khăn, nhưng nếu được viết tốt và nhắm mục tiêu vào các phần chính xác của mã của bạn, họ thực sự có thể tiết kiệm được một tấn của thời gian

Vấn đề lớn của tôi là với các khung thử nghiệm có sẵn. Tôi chưa bao giờ thực sự cảm thấy như họ là những gì tôi đang tìm kiếm, vì vậy tôi chỉ đưa ra giải pháp rất đơn giản của riêng mình. Nó thực sự giúp đưa tôi đến "mặt tối" của thử nghiệm hồi quy. Tôi sẽ chia sẻ một đoạn giả cơ bản về những gì tôi đã làm ở đây và hy vọng bạn có thể tìm thấy một giải pháp phù hợp với mình.

public interface ITest {
    public string Name {
        get;
    }
    public string Description {
        get;
    }
    public List<ITest> SubTests {
        get;
    }
    public TestResult Execute();
}

public class TestResult {
    public bool Succesful {
        get;
        set;
    }

    public string ResultMessage {
        get;
        set;
    }

    private Dictionary<ITest, TestResult> subTestResults = new Dictionary<ITest, TestResult>();
    public Dictionary<ITest, TestResult> SubTestResults {
        get {
            return subTestResults;
        }
        set {
            subTestResults = value;
        }
    }
}

Phần khó khăn duy nhất sau đó là tìm ra mức độ chi tiết mà bạn nghĩ là "bang for buck" tốt nhất cho bất kỳ dự án nào bạn đang làm.

Xây dựng một sổ địa chỉ sẽ đòi hỏi phải thử nghiệm ít hơn so với công cụ tìm kiếm doanh nghiệp, nhưng các nguyên tắc cơ bản không thực sự thay đổi.

Chúc may mắn!


Tôi nghĩ theo thời gian tôi sẽ tìm ra mức độ chi tiết nào là tốt nhất. Thật tốt khi nghe những người khác thường xuyên tạo ra các bài kiểm tra mà họ tiếp cận nó một cách hợp lý và không viết các bài kiểm tra bằng robot cho mọi kết quả có thể tưởng tượng được. Giới thiệu đầu tiên của tôi về các bài kiểm tra là ở mức độ mà mọi thứ phải được kiểm tra. Trên thực tế, toàn bộ khái niệm về TDD dường như tuân theo câu thần chú đó.
Ken Pespisa

Tôi nghĩ rằng bạn có thể hưởng lợi từ việc sử dụng Khung như SubSpec (được lấy cảm hứng từ BDD), do đó sẽ cho phép bạn nhận được Cách ly Assert ("SubTest") trong khi chia sẻ cài đặt ngữ cảnh.
Julian Rudolph
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.