it-swarm-vi.com

Bạn nên kiểm tra những gì với bài kiểm tra đơn vị?

Tôi mới ra khỏi trường đại học, và bắt đầu học đại học ở đâu đó vào tuần tới. Chúng tôi đã thấy các bài kiểm tra đơn vị, nhưng chúng tôi không sử dụng chúng nhiều; và mọi người nói về họ, vì vậy tôi nghĩ có lẽ tôi nên làm một số.

Vấn đề là, tôi không biết cái gì để kiểm tra. Tôi có nên kiểm tra trường hợp phổ biến? Trường hợp cạnh? Làm thế nào để tôi biết rằng một chức năng được bảo hiểm đầy đủ?

Tôi luôn có cảm giác khủng khiếp rằng trong khi một bài kiểm tra sẽ chứng minh rằng một hàm hoạt động trong một trường hợp nhất định, thì nó hoàn toàn vô dụng để chứng minh rằng hàm đó hoạt động, theo thời gian.

128
zneak

Triết lý cá nhân của tôi đã được như vậy:

  1. Kiểm tra trường hợp phổ biến của tất cả mọi thứ bạn có thể. Điều này sẽ cho bạn biết khi nào mã đó bị hỏng sau khi bạn thực hiện một số thay đổi (theo ý kiến ​​của tôi, đó là lợi ích lớn nhất của thử nghiệm đơn vị tự động).
  2. Kiểm tra các trường hợp Edge của một vài mã phức tạp khác thường mà bạn nghĩ có thể sẽ có lỗi.
  3. Bất cứ khi nào bạn tìm thấy một lỗi, hãy viết một trường hợp thử nghiệm để che nó trước khi sửa nó
  4. Thêm các bài kiểm tra trường hợp Edge vào mã ít quan trọng hơn bất cứ khi nào ai đó có thời gian để giết.
124
Fishtoaster

Trong số rất nhiều câu trả lời, do đó, không ai chạm vào phân vùng tương đươngphân tích giá trị biên , những cân nhắc quan trọng trong câu trả lời cho câu hỏi. Tất cả các câu trả lời khác, mặc dù hữu ích, là định tính nhưng có thể - và tốt hơn - là định lượng ở đây. @fishtoaster cung cấp một số hướng dẫn cụ thể, chỉ cần nhìn trộm dưới vỏ bọc của định lượng thử nghiệm, nhưng phân vùng tương đương và phân tích giá trị biên cho phép chúng tôi làm tốt hơn.

Trong phân vùng tương đương , bạn chia tập hợp tất cả các đầu vào có thể thành các nhóm dựa trên kết quả mong đợi. Bất kỳ đầu vào nào từ một nhóm sẽ mang lại kết quả tương đương, do đó các nhóm như vậy được gọi là các lớp tương đương. (Lưu ý rằng kết quả tương đương không không có nghĩa là kết quả giống hệt nhau.)

Như một ví dụ đơn giản, hãy xem xét một chương trình nên chuyển đổi chữ thường ASCII ký tự thành ký tự viết hoa. Các ký tự khác sẽ trải qua một chuyển đổi nhận dạng, tức là không thay đổi. Đây là một phân tích có thể thành các lớp tương đương:

| # |  Equivalence class    | Input        | Output       | # test cases |
+------------------------------------------------------------------------+
| 1 | Lowercase letter      | a - z        | A - Z        | 26           |
| 2 | Uppercase letter      | A - Z        | A - Z        | 26           |
| 3 | Non-alphabetic chars  | [email protected]#,/"... | [email protected]#,/"... | 42           |
| 4 | Non-printable chars   | ^C,^S,TAB... | ^C,^S,TAB... | 34           |

Cột cuối cùng báo cáo số lượng các trường hợp thử nghiệm nếu bạn liệt kê tất cả chúng. Về mặt kỹ thuật, theo quy tắc 1 của @ fishtoaster, bạn sẽ bao gồm 52 trường hợp thử nghiệm - tất cả các trường hợp cho hai hàng đầu tiên được đưa ra ở trên đều thuộc "trường hợp chung". Quy tắc 2 của fishtoaster cũng sẽ thêm một số hoặc tất cả từ hàng 3 và 4 ở trên. Nhưng với kiểm tra phân vùng tương đương, bất kỳ trường hợp kiểm tra nào trong mỗi lớp tương đương là đủ. Nếu bạn chọn "a" hoặc "g" hoặc "w", bạn đang kiểm tra cùng một đường dẫn mã. Như vậy, bạn có tổng cộng 4 trường hợp thử nghiệm thay vì 52+.

Phân tích giá trị biên đề xuất một sàng lọc nhỏ: về cơ bản, nó gợi ý rằng không phải mọi thành viên của một lớp tương đương là tốt, tương đương. Đó là, các giá trị tại các ranh giới cũng nên được coi là xứng đáng với một trường hợp thử nghiệm theo quyền riêng của chúng. (Một cách biện minh dễ dàng cho điều này là sự khét tiếng lỗi do lỗi một !) Vì vậy, với mỗi lớp tương đương, bạn có thể có 3 đầu vào kiểm tra. Nhìn vào miền đầu vào ở trên - và với một số kiến ​​thức về ASCII - tôi có thể đưa ra các đầu vào trường hợp thử nghiệm này:

| # | Input                | # test cases |
| 1 | a, w, z              | 3            |
| 2 | A, E, Z              | 3            |
| 3 | 0, 5, 9, !, @, *, ~  | 7            |
| 4 | nul, esc, space, del | 4            |

(Ngay sau khi bạn nhận được nhiều hơn 3 giá trị ranh giới cho thấy bạn có thể muốn suy nghĩ lại về các phân định lớp tương đương ban đầu của mình, nhưng điều này đủ đơn giản để tôi không quay lại để sửa đổi chúng.) Vì vậy, phân tích giá trị ranh giới đưa chúng ta đến 17 trường hợp thử nghiệm - với độ tin cậy cao về phạm vi bảo hiểm hoàn chỉnh - so với 128 trường hợp thử nghiệm để thực hiện thử nghiệm toàn diện. (Không đề cập đến việc tổ hợp ra lệnh rằng thử nghiệm toàn diện đơn giản là không khả thi đối với bất kỳ ứng dụng trong thế giới thực nào!)

68
Michael Sorens

Có lẽ ý kiến ​​của tôi không quá phổ biến. Nhưng tôi đề nghị bạn nên tiết kiệm với các bài kiểm tra đơn vị. Nếu bạn có quá nhiều bài kiểm tra đơn vị, bạn có thể dễ dàng dành một nửa thời gian hoặc nhiều hơn cho việc duy trì các bài kiểm tra thay vì mã hóa thực tế.

Tôi đề nghị bạn viết bài kiểm tra cho những thứ bạn có cảm giác xấu trong ruột hoặc những thứ rất quan trọng và/hoặc sơ cấp. Các bài kiểm tra đơn vị IMHO không phải là sự thay thế cho kỹ thuật tốt và mã hóa phòng thủ. Hiện tại tôi đang làm việc trong một dự án ít nhiều không thể tin được. Nó thực sự ổn định nhưng là một nỗi đau để tái cấu trúc. Trong thực tế, không ai chạm vào mã này trong một năm và ngăn xếp phần mềm dựa trên đó là 4 năm. Tại sao? Bởi vì nó lộn xộn với các bài kiểm tra đơn vị, chính xác là: Kiểm tra đơn vị và kiểm tra tích hợp tự động hóa. (Bạn đã từng nghe về dưa chuột và những thứ tương tự chưa?) : D

Vì vậy, đề nghị của tôi là:

  • Bắt đầu viết bài kiểm tra sa bạn đã phát triển bộ xương cơ bản, nếu không việc tái cấu trúc có thể gây đau đớn. Là một nhà phát triển phát triển cho người khác, bạn không bao giờ có được các yêu cầu ngay khi bắt đầu.

  • Hãy chắc chắn rằng bài kiểm tra đơn vị của bạn có thể được thực hiện nhanh chóng. Nếu bạn có các bài kiểm tra tích hợp (như dưa chuột) thì không sao nếu chúng mất nhiều thời gian hơn. Nhưng các bài kiểm tra chạy dài không có gì thú vị, tin tôi đi. (Mọi người quên tất cả lý do tại sao C++ trở nên ít phổ biến hơn ...)

  • Để lại công cụ TDD này cho các chuyên gia TDD.

  • Và vâng, đôi khi bạn tập trung vào các trường hợp Edge, đôi khi vào các trường hợp phổ biến, tùy thuộc vào nơi bạn mong đợi điều bất ngờ. Mặc dù nếu bạn luôn mong đợi những điều bất ngờ, bạn nên thực sự suy nghĩ lại về quy trình làm việc và kỷ luật của bạn. ;-)

20
Philip

Nếu bạn đang thử nghiệm đầu tiên với Phát triển theo hướng thử nghiệm, thì phạm vi bảo hiểm của bạn sẽ tăng lên trong phạm vi 90% hoặc cao hơn, bởi vì bạn sẽ không thêm chức năng mà không viết thử nghiệm đơn vị thất bại cho nó.

Nếu bạn đang thêm các bài kiểm tra sau khi thực tế, thì tôi không thể khuyên bạn nên lấy một bản sao của Làm việc hiệu quả với Mã kế thừa by Michael Feathers và xem một số các kỹ thuật cho cả việc thêm các bài kiểm tra vào mã của bạn và các cách tái cấu trúc mã của bạn để làm cho nó dễ kiểm tra hơn.

8
Paddyslacker

Nếu bạn bắt đầu theo dõi Phát triển theo hướng thử nghiệm thực hành, họ sẽ sắp xếp hướng dẫn bạn thông qua quy trình và biết những gì sẽ kiểm tra sẽ diễn ra một cách tự nhiên. Một số nơi để bắt đầu:

Các thử nghiệm đến trước

Không bao giờ, viết mã trước khi viết bài kiểm tra. Xem Red-Green-Refactor-Lặp lại để được giải thích.

Viết kiểm tra hồi quy

Bất cứ khi nào bạn gặp lỗi, hãy viết một testcase và đảm bảo rằng nó không thành công . Trừ khi bạn có thể tái tạo một lỗi thông qua một thử nghiệm thất bại, bạn thực sự không tìm thấy nó.

Red-Green-Refactor-Lặp lại

Red: Bắt đầu bằng cách viết một bài kiểm tra cơ bản nhất cho hành vi mà bạn đang cố gắng thực hiện. Hãy nghĩ về bước này khi viết một số mã ví dụ sử dụng lớp hoặc hàm mà bạn đang làm việc. Đảm bảo rằng nó biên dịch/không có lỗi cú pháp và nó không thành công . Điều này là hiển nhiên: bạn chưa viết bất kỳ mã nào, vì vậy nó phải thất bại, phải không? Điều quan trọng cần học ở đây là trừ khi bạn thấy bài kiểm tra thất bại ít nhất một lần, bạn không bao giờ có thể chắc chắn rằng nếu nó vượt qua, nó sẽ làm điều đó vì một điều gì đó mà bạn đã làm vì lý do không có thật.

Green: Viết mã đơn giản và ngu ngốc nhất thực sự khiến bài kiểm tra vượt qua. Đừng cố tỏ ra thông minh. Ngay cả khi bạn thấy rằng có một trường hợp Edge rõ ràng nhưng bài kiểm tra có tính đến tài khoản, đừng viết mã để xử lý nó (nhưng đừng quên trường hợp Edge: bạn sẽ cần nó một lát sau). Ý tưởng là mỗi đoạn mã yo viết, mọi if, mỗi try: ... except: ... nên được chứng minh bằng một trường hợp thử nghiệm. Mã không cần phải thanh lịch, nhanh chóng hoặc tối ưu hóa. Bạn chỉ muốn bài kiểm tra vượt qua.

Refactor: Dọn sạch mã của bạn, lấy đúng tên phương thức. Xem thử nghiệm vẫn còn vượt qua. Tối ưu hóa. Chạy thử lại.

Lặp lại: Bạn nhớ trường hợp Edge mà bài kiểm tra không bao gồm, phải không? Vì vậy, bây giờ là thời điểm quan trọng của nó. Viết một testcase bao gồm tình huống đó, xem nó thất bại, viết một số mã, xem nó vượt qua, tái cấu trúc.

Kiểm tra của bạn

Bạn đang làm việc trên một số đoạn mã cụ thể và đây chính xác là những gì bạn muốn kiểm tra. Điều này có nghĩa là bạn không nên kiểm tra các chức năng thư viện, thư viện chuẩn hoặc trình biên dịch của bạn. Ngoài ra, cố gắng tránh thử nghiệm "thế giới". Điều này bao gồm: gọi API web bên ngoài, một số nội dung chuyên sâu về cơ sở dữ liệu, v.v ... Bất cứ khi nào bạn có thể cố gắng giả lập nó (tạo một đối tượng theo cùng giao diện, nhưng trả về dữ liệu tĩnh, được xác định trước).

6
Ryszard Szopa

Đối với các bài kiểm tra đơn vị, hãy bắt đầu với kiểm tra rằng nó thực hiện những gì nó được thiết kế để làm. Đó phải là trường hợp đầu tiên bạn viết. Nếu một phần của thiết kế là "nó sẽ ném một ngoại lệ nếu bạn vượt qua rác", hãy kiểm tra điều đó vì đó là một phần của thiết kế.

Bắt đầu với điều đó. Khi bạn có kinh nghiệm thực hiện việc kiểm tra cơ bản nhất đó, bạn sẽ bắt đầu tìm hiểu xem điều đó có đủ hay không và bắt đầu thấy các khía cạnh khác của mã cần kiểm tra.

3
Bryan Oakley

Câu trả lời chứng khoán là "kiểm tra mọi thứ có thể phá vỡ" .

Những gì quá đơn giản để phá vỡ? Các trường dữ liệu, bộ truy cập thuộc tính chết não và trên đầu nồi hơi tương tự. Bất cứ điều gì khác có thể thực hiện một số phần có thể xác định được của một yêu cầu và có thể được hưởng lợi từ việc được kiểm tra.

Tất nhiên, số dặm của bạn - và thực tiễn môi trường làm việc của bạn - có thể khác nhau.

0
Jeffrey Hantin