Đơn vị kiểm tra các thành phần nội bộ


14

Ở mức độ nào bạn đơn vị kiểm tra các thành phần nội bộ / riêng tư của một lớp / mô-đun / gói / vv? Bạn có kiểm tra chúng không hay bạn chỉ kiểm tra giao diện với thế giới bên ngoài? Một ví dụ về những nội bộ này là phương thức riêng tư.

Ví dụ, hãy tưởng tượng một trình phân tích cú pháp gốc đệ quy , có một số thủ tục nội bộ (hàm / phương thức) được gọi từ một thủ tục trung tâm. Giao diện duy nhất với thế giới bên ngoài là thủ tục trung tâm, lấy một chuỗi và trả về thông tin được phân tích cú pháp. Các thủ tục khác phân tích các phần khác nhau của chuỗi và chúng được gọi từ thủ tục trung tâm hoặc các thủ tục khác.

Đương nhiên, bạn nên kiểm tra giao diện bên ngoài bằng cách gọi nó bằng các chuỗi mẫu và so sánh nó với đầu ra được phân tích cú pháp. Nhưng những gì về các thủ tục khác? Bạn có kiểm tra chúng riêng lẻ để kiểm tra xem chúng phân tích chính xác các chuỗi con của chúng không?

Tôi có thể nghĩ về một vài lập luận:

Ưu điểm :

  1. Thử nghiệm nhiều hơn luôn luôn tốt hơn và điều này có thể giúp tăng phạm vi bảo hiểm mã
  2. Một số thành phần bên trong có thể khó đưa ra đầu vào cụ thể (ví dụ trường hợp cạnh) bằng cách cung cấp đầu vào cho giao diện bên ngoài
  3. Kiểm tra rõ ràng hơn. Nếu một thành phần bên trong có lỗi (đã sửa), trường hợp kiểm tra cho thành phần đó cho thấy rõ lỗi đó nằm trong thành phần cụ thể đó

Nhược điểm :

  1. Tái cấu trúc trở nên quá đau đớn và tốn thời gian. Để thay đổi bất cứ điều gì, bạn cần viết lại các bài kiểm tra đơn vị, ngay cả khi người dùng giao diện bên ngoài không bị ảnh hưởng
  2. Một số ngôn ngữ và khung kiểm tra không cho phép nó

Ý kiến ​​của bạn là gì?


trùng lặp có thể xảy ra hoặc trùng lặp đáng kể với: lập trình
viên.stackexchange.com/questions/10832/iêu

Câu trả lời:


8

Trường hợp: một "mô-đun" (trong một phạm vi rộng, nghĩa là một cái gì đó có giao diện chung và có thể cả một số phần bên trong riêng tư) có một số logic phức tạp / liên quan bên trong nó. Chỉ kiểm tra giao diện mô-đun sẽ là một loại thử nghiệm tích hợp liên quan đến cấu trúc bên trong của mô-đun, và do đó, trong trường hợp phát hiện ra lỗi, thử nghiệm đó sẽ không bản địa hóa phần / thành phần chính xác chịu trách nhiệm cho lỗi.

Giải pháp: tự biến các phần bên trong phức tạp thành các mô-đun, kiểm tra đơn vị chúng (và lặp lại các bước này cho chúng nếu chúng quá phức tạp) và nhập vào mô-đun ban đầu của bạn. Bây giờ bạn chỉ có một bộ mô-đun đủ đơn giản để kiểm tra đơn giản (cả hai đều kiểm tra hành vi đó có đúng và sửa lỗi không) một cách dễ dàng, và đó là tất cả.

Ghi chú:

  • sẽ không cần thay đổi bất cứ điều gì trong các thử nghiệm "mô-đun phụ" của mô-đun (trước đây) khi thay đổi hợp đồng của mô-đun, trừ khi "mô-đun phụ" không còn cung cấp dịch vụ đủ để thực hiện hợp đồng mới / đã thay đổi.

  • không có gì sẽ được công khai một cách không cần thiết, tức là hợp đồng của mô-đun sẽ được giữ và việc đóng gói được duy trì.

[Cập nhật]

Để kiểm tra một số logic bên trong thông minh trong các trường hợp khó đưa các phần bên trong của đối tượng (ý tôi là các thành viên không phải là các mô-đun / gói được nhập riêng) vào trạng thái thích hợp chỉ bằng cách cho nó nhập thông qua giao diện chung của đối tượng:

  • chỉ cần có một số mã kiểm tra với quyền truy cập của bạn bè (theo thuật ngữ C ++) hoặc gói (Java) vào các bộ phận thực sự đặt trạng thái từ bên trong và kiểm tra hành vi như bạn muốn.

    • điều này sẽ không phá vỡ đóng gói một lần nữa trong khi cung cấp quyền truy cập trực tiếp dễ dàng vào bên trong cho mục đích thử nghiệm - chỉ cần chạy thử nghiệm dưới dạng "hộp đen" và biên dịch chúng trong các bản dựng phát hành.

và bố cục danh sách dường như bị phá vỡ một chút; (
mlvljr

1
Câu trả lời tốt. Trong .NET, bạn có thể sử dụng [assembly: InternalsVisibleTo("MyUnitTestAssembly")]thuộc tính trong của bạn AssemblyInfo.csđể kiểm tra nội bộ. Nó cảm thấy như gian lận mặc dù.
Không ai là

@rmx Một khi một cái gì đó đáp ứng tất cả các tiêu chí cần thiết, nó không phải là gian lận ngay cả khi có điểm chung với gian lận thực tế. Nhưng chủ đề truy cập giữa các mô-đun / nội bộ thực sự là một chút bị hạn chế trong các ngôn ngữ chính hiện đại.
mlvljr

2

Cách tiếp cận mã dựa trên FSM hơi khác so với cách sử dụng truyền thống. Nó rất giống với những gì được mô tả ở đây để kiểm tra phần cứng (thường là một FSM).

Nói tóm lại, bạn tạo một chuỗi đầu vào thử nghiệm (hoặc một chuỗi các chuỗi đầu vào thử nghiệm) không chỉ tạo ra một đầu ra nhất định mà cả khi tạo ra một đầu ra "xấu" cụ thể cho phép xác định thành phần bị lỗi theo bản chất của lỗi. Cách tiếp cận khá có khả năng mở rộng, bạn càng dành nhiều thời gian cho thiết kế thử nghiệm thì thử nghiệm sẽ càng tốt.

Loại thử nghiệm này gần với cái gọi là "thử nghiệm chức năng" nhưng nó loại bỏ sự cần thiết phải thay đổi thử nghiệm mỗi khi bạn chạm nhẹ vào một triển khai.


2

Vâng - nó phụ thuộc :-). Nếu bạn đang theo phương pháp BDD (Phát triển hướng hành vi) hoặc phương pháp ATDD (Phát triển dựa trên thử nghiệm chấp nhận) thì kiểm tra giao diện công cộng là tốt (miễn là bạn kiểm tra triệt để với các đầu vào khác nhau. thực sự quan trọng

Tuy nhiên, nói rằng bạn muốn một phần của thuật toán đó thực thi trong một khung thời gian nhất định hoặc dọc theo một đường cong bigO nhất định (ví dụ: nlogn) thì có kiểm tra các phần riêng lẻ. Một số người sẽ gọi đây là cách tiếp cận TDD / Unit Test truyền thống.

Như với mọi thứ, YMMV


1

Chia nó thành nhiều phần với một ý nghĩa chức năng, ví dụ như ParseQuotedString(), ParseExpression(), ParseStatement(), ParseFile()và làm cho họ tất cả cộng đồng. Làm thế nào có khả năng là cú pháp của bạn thay đổi nhiều đến mức những điều này trở nên không liên quan?


1
Cách tiếp cận này dễ dàng dẫn đến việc đóng gói yếu hơn và các giao diện lớn hơn và khó sử dụng hơn.
sara
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.