Làm thế nào để thực hiện một thử nghiệm phụ thuộc vào kết quả của một thử nghiệm khác?


13

Giả sử có một lớp tiện ích cung cấp một số phương thức tĩnh phổ biến được sử dụng ở mọi nơi trong mã của bạn bởi nhiều lớp khác.

Làm thế nào bạn sẽ thiết kế các thử nghiệm đơn vị của mình cho người tiêu dùng tiện ích để các thử nghiệm của họ thất bại nếu bất kỳ một trong các thử nghiệm tiện ích nào không vượt qua? Bạn có thể làm điều đó hoặc bạn phải tự kiểm tra xem các bài kiểm tra lớp tiện ích có màu xanh không?

Ví dụ: tôi có một tiện ích phân tách thông điệp được sử dụng (hay đúng hơn là đầu ra của nó) bởi một trình phân tích cú pháp thư. Tôi muốn chắc chắn rằng trình phân tách thông báo hoạt động chính xác trước khi trình phân tích cú pháp thư được kiểm tra.

Tôi đã viết bài kiểm tra cho cả hai nhưng có cách nào để liên kết chúng và làm một bài kiểm tra phụ thuộc vào kết quả của một bài kiểm tra khác không?

Tôi không thể tìm thấy một thẻ phù hợp cho việc này nhưng tôi đang sử dụng công cụ kiểm tra đơn vị của Visual Studio.


1
Tôi hiểu rằng trình phân tích cú pháp không hoạt động chính xác nếu tiện ích không thành công. Nhưng nếu bạn chạy thử nghiệm, bạn sẽ thấy các thử nghiệm tiện ích thất bại. Tại sao bạn muốn các bài kiểm tra khác cũng thất bại?
Eugen Martynov

1
Tôi chưa bao giờ nghe về bất cứ ai muốn điều này trước đây. Bạn đang cố gắng để đạt được điều gì?
Esben Skov Pedersen


Tôi sử dụng một số chức năng tiện ích để chuẩn bị dữ liệu cho các bài kiểm tra trình phân tích cú pháp vì vậy tôi muốn chắc chắn rằng tiện ích này hoạt động chính xác trước khi tôi kiểm tra mọi thứ khác.
t3chb0t

3
@ t3chb0t Nếu bạn muốn đảm bảo tiện ích của mình hoạt động thì bạn cần phải viết bài kiểm tra đơn vị để xác minh tiện ích của bạn. Các bài kiểm tra đơn vị nên là nguyên tử. Bạn chỉ muốn họ thử nghiệm một thành phần duy nhất.
maple_shaft

Câu trả lời:


11

Không có điểm nào để đảm bảo rằng mọi khiếm khuyết trong các chuyến đi hệ thống của bạn chính xác một bài kiểm tra.

Một bộ kiểm tra có một công việc: xác minh rằng không có lỗi được biết đến. Nếu có lỗi, sẽ không thành vấn đề nếu một thử nghiệm thất bại hoặc 10. Nếu bạn quen với bộ thử nghiệm của mình không thành công, nếu bạn cố gắng đánh giá mức độ "xấu" của chương trình của bạn bằng cách đếm các thử nghiệm thất bại, bạn sẽ không sử dụng kiểm tra hồi quy đúng cách. Bộ kiểm tra phải vượt qua tất cả kiểm tra trước khi bạn xuất bản mã.

Lý do duy nhất hợp lệ để bỏ qua các bài kiểm tra là nếu chúng kiểm tra chức năng không đầy đủ mất một lượng thời gian không phù hợp mà bạn có thể sử dụng tốt hơn trong khi thực hiện điều mà chúng đáng lẽ phải kiểm tra. (Đó chỉ là một vấn đề nếu bạn không thực hành phát triển dựa trên thử nghiệm nghiêm ngặt, nhưng rốt cuộc đó là một lựa chọn hợp lệ.)

Nếu không, đừng cố gắng biến bộ kiểm tra của bạn thành một chỉ báo cho bạn biết chính xác những gì sai. Nó sẽ không bao giờ chính xác, và nó không phải là như vậy. Điều đó có nghĩa là bảo vệ bạn khỏi mắc lỗi tương tự hai lần, chỉ vậy thôi.


8

Nó phụ thuộc vào dụng cụ của bạn, nhưng có lẽ bạn không thể (và không nên)

Một số khung kiểm thử đơn vị (lấy PHPUnit ví dụ ) cho phép bạn 'kiểm tra chuỗi' để thử nghiệm thất bại ở một cấp độ không thực hiện các thử nghiệm khác. Tuy nhiên, tôi nghi ngờ rằng điều này sẽ khắc phục vấn đề của bạn cho tình huống này.

Không cho phép thực thi lệnh kiểm tra được bảo đảm buộc các phép thử tách biệt với nhau và thường được coi là một điều tốt. Hãy tưởng tượng điều gì sẽ xảy ra nếu các bài kiểm tra không chỉ tự chạy mà còn cung cấp dữ liệu cho các bài kiểm tra khác hoạt động trên ...

Bạn có thể đặt các phương thức tiện ích này trong một giải pháp hoặc danh mục kiểm tra riêng. Hãy chắc chắn rằng chúng trực quan 'nổi bật' trong trình chạy thử của bạn hoặc danh mục này chạy trước và không chạy bất kỳ thử nghiệm nào khác nếu các thử nghiệm trong danh mục này không thành công *. Khi một trong những thử nghiệm này thất bại, thất bại có thể sẽ xếp tầng trên tất cả các thử nghiệm và bạn nên giúp đảm bảo rằng bất cứ ai chạy thử nghiệm đều biết bắt đầu bằng cách sửa chữa các thử nghiệm thất bại này trước hết. Điều tương tự cũng xảy ra đối với các bài kiểm tra đơn vị và kiểm tra tích hợp. Nếu một Unittest thất bại, nó sẽ xếp tầng và gây ra tất cả các loại tình trạng lộn xộn trong các bài kiểm tra Tích hợp. Mọi người đều biết rằng khi các bài kiểm tra Đơn vị và Tích hợp thất bại, bạn bắt đầu bằng cách kiểm tra Unittests ...

* Với tập lệnh xây dựng hoặc kiểm tra tự động, bạn có thể chạy danh mục này trước, kiểm tra kết quả và chỉ chạy các kiểm tra khác nếu đợt kiểm tra đầu tiên này vượt qua.


5

Hãy thử giữ nguyên tử thử nghiệm đơn vị của bạn. Hãy nhớ rằng mã kiểm tra tự động cũng là một phần của cơ sở mã của bạn, nhưng bản thân nó không được kiểm tra, vì vậy hãy giữ nó đơn giản và rõ ràng nhất có thể.

Để trả lời câu hỏi của bạn trực tiếp hơn, không có gì đảm bảo về thứ tự thực hiện các bài kiểm tra vì vậy cũng không có cách nào để đảm bảo rằng bài kiểm tra tiện ích của bạn thành công trước khi các bài kiểm tra khác của bạn được chạy. Vì vậy, không có cách nào đảm bảo để đạt được những gì bạn muốn trong khi vẫn có một bộ kiểm tra duy nhất cho tất cả các bài kiểm tra của bạn.

Bạn có thể di chuyển các tiện ích sang giải pháp của riêng họ và thêm một tham chiếu đến dll kết quả của nó trong dự án hiện tại của bạn.


4

Tóm lại, bạn không muốn sử dụng các công cụ / kỹ thuật để làm những việc khác ngoài mục đích của chúng.

Những gì bạn đang cố gắng để làm âm thanh như một mối quan tâm có thể được giải quyết dễ dàng với thực hành CI (tích hợp liên tục).

Bằng cách này, bạn có thể giữ các bài kiểm tra của mình nguyên tử như đã đề xuất và để CI chăm sóc xác minh các bài kiểm tra của bạn.

Nếu bất kỳ thử nghiệm nào thất bại, bạn có thể đặt nó để nó không cho phép mã của bạn được xuất bản.


4

Tôi có thói quen luôn cố gắng phân biệt mã cấp độ ứng dụng với mã cấp khung, vì vậy tôi đã gặp phải vấn đề mà bạn đang mô tả khá thường xuyên: bạn thường muốn tất cả mã cấp độ khung được kiểm tra trước khi bất kỳ mã cấp độ ứng dụng nào bắt đầu được kiểm tra . Ngoài ra, ngay cả trong mã cấp khung, có xu hướng có một số mô-đun khung cơ bản được sử dụng bởi tất cả các mô-đun khung khác, và nếu có lỗi trong nguyên tắc cơ bản, thực sự không có điểm nào trong việc kiểm tra bất cứ điều gì khác.

Thật không may, các nhà cung cấp khung thử nghiệm có xu hướng có những ý tưởng hơi cứng nhắc về cách sử dụng sáng tạo của họ, và khá bảo vệ những ý tưởng đó, trong khi những người sử dụng khung của họ có xu hướng chấp nhận mục đích sử dụng mà không cần hỏi. Đây là vấn đề, bởi vì nó kìm hãm thử nghiệm và đổi mới. Tôi không biết về những người khác, nhưng tôi thích tự do thử làm điều gì đó một cách kỳ quặc và tự mình xem liệu kết quả tốt hơn hay xấu hơn so với cách đã được thiết lập, thay vì không có quyền tự do làm mọi thứ theo cách của tôi ở nơi đầu tiên.

Vì vậy, theo tôi, sự phụ thuộc kiểm tra sẽ là một điều tuyệt vời cần có, và thay vào đó, khả năng chỉ định thứ tự thực hiện các bài kiểm tra sẽ là điều tốt nhất tiếp theo.

Cách duy nhất tôi tìm thấy để giải quyết vấn đề đặt hàng thử nghiệm là đặt tên cẩn thận, để khai thác xu hướng của khung thử nghiệm để thực hiện thử nghiệm theo thứ tự bảng chữ cái.

Tôi không biết làm thế nào điều này hoạt động trong Visual Studio, vì tôi chưa làm gì liên quan đến thử nghiệm rộng rãi với C #, nhưng ở phía Java của thế giới, nó hoạt động như sau: Trong thư mục nguồn của dự án, chúng tôi thường có hai thư mục con, một cái gọi là "chính", chứa mã sản xuất và một cái gọi là "thử nghiệm", chứa mã thử nghiệm. Trong "chính", chúng tôi có một hệ thống phân cấp thư mục tương ứng chính xác với hệ thống phân cấp gói của mã nguồn của chúng tôi. Các gói Java gần tương ứng với các không gian tên C #. C # không yêu cầu bạn khớp phân cấp thư mục với phân cấp không gian tên, nhưng nên làm như vậy.

Bây giờ, những gì mọi người thường làm trong thế giới Java là trong thư mục "test", họ phản ánh hệ thống phân cấp thư mục được tìm thấy trong thư mục "chính", để mỗi thử nghiệm nằm trong cùng một gói chính xác như lớp mà nó kiểm tra. Lý do đằng sau điều này là khá thường xuyên lớp thử nghiệm cần truy cập các thành viên gói riêng của lớp đang thử nghiệm, vì vậy lớp thử nghiệm cần phải nằm trong cùng gói với lớp được thử. Ở phía C # của thế giới không có thứ gọi là khả năng hiển thị không gian tên cục bộ, vì vậy không có lý do gì để phản ánh hệ thống phân cấp thư mục, nhưng tôi nghĩ rằng các lập trình viên C # ít nhiều tuân theo cùng một quy tắc trong việc cấu trúc các thư mục của họ.

Trong mọi trường hợp, tôi thấy toàn bộ ý tưởng này cho phép các lớp kiểm tra có quyền truy cập vào các thành viên gói cục bộ của các lớp được kiểm tra sai, bởi vì tôi có xu hướng kiểm tra các giao diện, không phải triển khai. Vì vậy, hệ thống phân cấp thư mục của các thử nghiệm của tôi không phải phản ánh phân cấp thư mục của mã sản xuất của tôi.

Vì vậy, những gì tôi làm là tôi đặt tên cho các thư mục (nghĩa là các gói) của các thử nghiệm của tôi như sau:

t001_SomeSubsystem
t002_SomeOtherSubsystem
t003_AndYetAnotherSubsystem
...

Điều này đảm bảo rằng tất cả các thử nghiệm cho "Một số hệ thống" sẽ được thực hiện trước tất cả các thử nghiệm cho "Một số hệ thống khác", tất cả các thử nghiệm sẽ được thực hiện trước tất cả các thử nghiệm cho "AndYetAnotherSubystem", v.v.

Trong một thư mục, các tệp thử nghiệm riêng lẻ được đặt tên như sau:

T001_ThisTest.java
T002_ThatTest.java
T003_TheOtherTest.java

Tất nhiên, điều đó giúp ích rất nhiều cho các IDE hiện đại có khả năng tái cấu trúc mạnh mẽ cho phép bạn đổi tên toàn bộ các gói (và tất cả các gói phụ và tất cả các mã tham chiếu đến chúng) chỉ bằng vài cú nhấp chuột và tổ hợp phím.


2
I don't know about everyone else, but I would prefer to have the freedom to try to do something in an odd way, and see for myself whether the results are better or worse++ bạn đời. Tôi không biết rằng tôi thích giải pháp, nhưng tôi thích thái độ bạn đã thể hiện ở đó.
RubberDuck
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.