Có phải là thực tế xấu để thực thi một lệnh thực hiện cho các bài kiểm tra đơn vị?


84

Tôi đang viết bài kiểm tra cho một dự án bao gồm nhiều mô hình con. Mỗi trường hợp thử nghiệm mà tôi đã viết chạy độc lập với nhau và tôi xóa tất cả dữ liệu giữa các thử nghiệm.

Mặc dù các bài kiểm tra chạy độc lập, tôi đang xem xét thực thi lệnh thực thi, vì một số trường hợp yêu cầu nhiều hơn một mô hình con. Ví dụ, một mô hình con đang tạo dữ liệu và một mô hình khác đang chạy truy vấn trên dữ liệu. Nếu mô hình con tạo dữ liệu có lỗi, kiểm tra mô hình con truy vấn cũng sẽ thất bại, ngay cả khi chính mô hình con hoạt động tốt.

Tôi không thể làm việc với dữ liệu giả, vì chức năng chính tôi đang kiểm tra là kết nối với máy chủ từ xa hộp đen, chỉ lấy dữ liệu từ mô hình con đầu tiên.

Trong trường hợp này, bạn có thể thi hành lệnh thi hành cho các bài kiểm tra hay không? Tôi cảm thấy như có một mùi trong thiết lập này, nhưng tôi không thể tìm thấy một cách tốt hơn xung quanh.

chỉnh sửa: câu hỏi là từ Làm thế nào để kiểm tra cấu trúc trong đó một thử nghiệm là thiết lập của thử nghiệm khác? vì kiểm tra "trước" không phải là thiết lập, nhưng kiểm tra mã thực hiện cài đặt.



123
Nếu bạn đang kiểm tra kết nối đến một máy chủ từ xa, thì theo định nghĩa, chúng không phải là kiểm tra đơn vị.
Telastyn

9
Câu trả lời đầu tiên làm tôi bối rối ở đây bởi vì trong tiêu đề của bạn, bạn đã nói "Có phải đó là thực hành xấu?" và trong phần tóm tắt câu hỏi của bạn, bạn đã viết "có ổn không?" Bất cứ ai trả lời có hoặc không sẽ nhầm lẫn một trong những điều đó!
Liath

8
Âm thanh như bạn đang tạo ra các thử nghiệm tích hợp. Ngay cả đối với một bài kiểm tra đó cũng không nên dựa vào các bài kiểm tra khác.
Low Flying Pelican

17
Nếu thứ tự quan trọng thì có lẽ bạn đang làm sai.
Mark Rogers

Câu trả lời:


236

Tôi không thể làm việc với dữ liệu giả, vì chức năng chính tôi đang kiểm tra là kết nối với máy chủ từ xa hộp đen, chỉ lấy dữ liệu từ mô hình con đầu tiên.

Đây là phần quan trọng đối với tôi. Bạn có thể nói về "kiểm tra đơn vị" và chúng "chạy độc lập với nhau", nhưng tất cả đều có vẻ như chúng phụ thuộc vào máy chủ từ xa này và phụ thuộc vào "mô-đun phụ đầu tiên". Vì vậy, mọi thứ âm thanh được kết hợp chặt chẽ và phụ thuộc vào trạng thái bên ngoài. Như vậy, trên thực tế bạn đang viết các bài kiểm tra tích hợp. Có những bài kiểm tra chạy theo một thứ tự cụ thể là khá bình thường vì chúng phụ thuộc nhiều vào các yếu tố bên ngoài. Một lần chạy thử đã ra lệnh, với tùy chọn thoát sớm khỏi lần chạy thử nếu xảy ra sự cố là hoàn toàn chấp nhận được đối với các thử nghiệm tích hợp.

Tuy nhiên, cũng đáng để xem xét cấu trúc ứng dụng của bạn. Có thể giả lập mô hình con đầu tiên và máy chủ bên ngoài sau đó có khả năng cho phép bạn viết các bài kiểm tra đơn vị thực sự cho tất cả các mô hình con khác.


14
Chưa kể rằng một số thử nghiệm phải kiểm tra cụ thể rằng hành vi dự kiến ​​xảy ra khi máy chủ từ xa không khả dụng.
Alexander

2
Hoặc, có lẽ, trên thực tế, bạn đang có ý định viết các bài kiểm tra tích hợp, và do đó, việc loại bỏ dữ liệu sẽ không đạt được những gì bạn đang cố gắng thực hiện với các bài kiểm tra này.
Guy Schalnat

10
Vấn đề rất có thể là Junit có "đơn vị" trong tên của nó.
Thorbjørn Ravn Andersen

7
@ ThorbjørnRavnAndersen Chính xác. Mọi người tự nhiên viết các bài kiểm tra tích hợp, thay vì các bài kiểm tra đơn vị, bởi vì các bài kiểm tra tích hợp đều hữu ích hơn rất nhiều và khó viết hơn rất nhiều so với các bài kiểm tra đơn vị "thực". Nhưng bởi vì các khung thử nghiệm phổ biến được đặt tên theo khái niệm thử nghiệm đơn vị, thuật ngữ này đã được đồng ý và có nghĩa là "bất kỳ thử nghiệm tự động" nào theo cách nói hiện đại.
Mason Wheeler

1
@MasonWheeler Hoặc thậm chí được các nhà quản lý kỹ thuật không đồng ý chọn để thử nghiệm chấp nhận.
TKK

32

Vâng, đó là một thực hành xấu.

Nói chung, một bài kiểm tra đơn vị nhằm kiểm tra một đơn vị mã (ví dụ: một hàm duy nhất dựa trên trạng thái đã biết).

Khi bạn muốn kiểm tra một chuỗi các sự kiện có thể xảy ra trong tự nhiên, bạn muốn có một kiểu thử nghiệm khác, chẳng hạn như thử nghiệm tích hợp. Điều này thậm chí còn đúng hơn nếu bạn phụ thuộc vào dịch vụ của bên thứ ba.

Để kiểm tra đơn vị những thứ như thế này, bạn cần tìm ra cách tiêm dữ liệu giả, ví dụ như thực hiện giao diện dịch vụ dữ liệu phản ánh yêu cầu web nhưng trả về dữ liệu đã biết từ tệp dữ liệu giả cục bộ.


8
Đã đồng ý. Tôi nghĩ rằng sự nhầm lẫn này xuất phát từ thực tế là nhiều người có ý tưởng rằng các bài kiểm tra tích hợp phải là đầu cuối và sử dụng "bài kiểm tra đơn vị" để chỉ bất kỳ bài kiểm tra nào chỉ kiểm tra một lớp .
autophage

8
@autophage: Chắc chắn đồng ý với điều này. Trong thực tế, tôi đồng ý với nó rất nhiều mà tôi thường xuyên thấy mình rơi vào cái bẫy tương tự mặc dù đồng ý rằng đó là một cái bẫy 😂
Lightness Races ở Orbit

16

Lệnh thực thi được thi hành mà bạn đề xuất chỉ có ý nghĩa nếu bạn cũng hủy bỏ quá trình chạy thử sau thất bại đầu tiên.

Hủy bỏ lần chạy thử trong lần thất bại đầu tiên có nghĩa là mỗi lần chạy thử chỉ có thể phát hiện ra một vấn đề duy nhất và nó không thể tìm thấy sự cố mới cho đến khi tất cả các sự cố trước đó đã được khắc phục. Nếu thử nghiệm đầu tiên để chạy tìm thấy sự cố mất một tháng để khắc phục, thì trong tháng đó có hiệu quả sẽ không có thử nghiệm nào được thực hiện.

Nếu bạn không hủy bỏ lần chạy thử trong lần thất bại đầu tiên, thì lệnh thực thi được thi hành sẽ không mua cho bạn bất cứ điều gì vì mỗi lần kiểm tra thất bại cần phải được điều tra. Ngay cả khi chỉ để xác nhận rằng thử nghiệm trên mô hình con truy vấn bị lỗi do lỗi cũng được xác định trên mô hình con tạo dữ liệu.

Lời khuyên tốt nhất tôi có thể đưa ra là viết các bài kiểm tra theo cách dễ xác định khi một thất bại trong sự phụ thuộc đang làm cho bài kiểm tra thất bại.


7

Mùi mà bạn đề cập đến là việc áp dụng sai các ràng buộc và quy tắc cho các bài kiểm tra của bạn.

Các thử nghiệm đơn vị thường bị nhầm lẫn với "thử nghiệm tự động" hoặc "thử nghiệm tự động bởi một lập trình viên".

Bài kiểm tra đơn vị phải nhỏ, độc lập và nhanh chóng.

Một số người đọc không chính xác điều này là "các bài kiểm tra tự động được viết bởi một lập trình viên phải độc lập nhỏ và nhanh" . Nhưng nó đơn giản có nghĩa là nếu các bài kiểm tra của bạn không nhỏ, độc lập và nhanh chóng, chúng không phải là Bài kiểm tra đơn vị, và do đó, một số quy tắc cho Bài kiểm tra đơn vị không nên, không thể hoặc không phải áp dụng cho bài kiểm tra của bạn. Một ví dụ tầm thường: bạn nên chạy Bài kiểm tra đơn vị của mình sau mỗi lần xây dựng, điều mà bạn không được thực hiện đối với các bài kiểm tra tự động không nhanh.

Mặc dù các bài kiểm tra của bạn không phải là Bài kiểm tra đơn vị có nghĩa là bạn có thể bỏ qua một quy tắc và được phép có một số phụ thuộc lẫn nhau giữa các bài kiểm tra, bạn cũng phát hiện ra rằng có những quy tắc khác mà bạn có thể đã bỏ qua và sẽ cần phải giới thiệu lại - một điều gì đó cho phạm vi của câu hỏi khác .


6

Như đã lưu ý ở trên, những gì bạn đang chạy dường như là một bài kiểm tra tích hợp, tuy nhiên bạn nói rằng:

Ví dụ, một mô hình con đang tạo dữ liệu và một mô hình khác đang chạy truy vấn trên dữ liệu. Nếu mô hình con tạo dữ liệu có lỗi, kiểm tra mô hình con truy vấn cũng sẽ thất bại, ngay cả khi chính mô hình con hoạt động tốt.

Và đây có thể là một nơi tốt để bắt đầu tái cấu trúc. Mô-đun chạy truy vấn trên dữ liệu không nên phụ thuộc vào việc triển khai cụ thể mô-đun (tạo dữ liệu) đầu tiên. Thay vào đó, tốt hơn là nên tiêm một giao diện chứa các phương thức để lấy dữ liệu đó và điều này sau đó có thể được thử nghiệm để kiểm tra các truy vấn.

ví dụ

Nếu bạn có:

class Queries {

    int GetTheNumber() {
        var dataModule = new Submodule1();
        var data = dataModule.GetData();
        return ... run some query on data
    }
}

Thay vào đó thích:

interface DataModule {
    Data GetData();
}


class Queries {

    IDataModule _dataModule;

    ctor(IDataModule dataModule) {
       _dataModule = dataModule;
    }

    int GetTheNumber() {
        var data = _dataModule.GetData();
        return ... run some query on data
    }
}

Điều này loại bỏ sự phụ thuộc khỏi các truy vấn trên nguồn dữ liệu của bạn và cho phép bạn thiết lập các thử nghiệm đơn vị dễ lặp lại cho các tình huống cụ thể.


6

Các câu trả lời khác đề cập đến việc kiểm tra thứ tự là xấu (hầu hết là đúng trong hầu hết thời gian), nhưng có một lý do chính đáng để thực thi lệnh khi thực hiện kiểm tra: đảm bảo các kiểm tra chậm của bạn (tức là kiểm tra tích hợp) chạy sau các kiểm tra nhanh hơn (kiểm tra không dựa vào các nguồn lực bên ngoài khác). Điều này đảm bảo rằng bạn thực hiện nhiều thử nghiệm nhanh hơn, có thể tăng tốc vòng phản hồi.


2
Tôi sẽ có xu hướng điều tra lý do tại sao một bài kiểm tra đơn vị nhất định đang chạy chậm hơn là thực thi một đơn đặt hàng. Các bài kiểm tra đơn vị được cho là nhanh chóng.
Robbie Dee

OP cho biết ông không thể làm việc với dữ liệu giả cho một số thử nghiệm này. Điều đó có nghĩa là một cú đánh cơ sở dữ liệu thuộc loại nào đó, làm chậm tất cả các bài kiểm tra (thậm chí một số bài kiểm tra đơn vị thực sự sẽ chạy nhanh một cách tự nhiên). Nếu anh ta có các bài kiểm tra khác không yêu cầu truy cập cơ sở dữ liệu, họ sẽ chạy một thứ tự cường độ nhanh hơn bất kỳ thứ gì yêu cầu truy cập đĩa hoặc mạng.
Mike Holler

2
Tôi nghĩ cả hai đều đúng; Robbie nói đúng rằng các bài kiểm tra đơn vị nên nhỏ và nhanh và tách biệt với các phụ thuộc vì vậy thứ tự không nên quan trọng và thứ tự ngẫu nhiên thường khuyến khích thiết kế tốt hơn bằng cách thực thi tính độc lập đó; và Mike nói đúng rằng việc chạy các bài kiểm tra nhanh hơn trước tiên là rất, rất tốt cho các bài kiểm tra tích hợp . Như trong các câu trả lời ở trên, một phần của vấn đề là thuật ngữ của đơn vị so với kiểm tra tích hợp.
WillC

@MikeHoller Sau đó, họ không phải là bài kiểm tra đơn vị. Thực sự không nên nhầm lẫn về các bài kiểm tra đơn vị là gì .
Robbie Dee

@RobbieDee Tôi chỉ đơn thuần sử dụng thuật ngữ mà OP đang sử dụng. Tôi hiểu rằng đây không phải là bài kiểm tra đơn vị thực sự. Nếu bạn muốn chiến đấu về thuật ngữ, hãy đưa nó lên với OP. (do đó tại sao tôi làm rõ với "bài kiểm tra đơn vị thực sự" trong nhận xét trước đó của tôi ")
Mike Holler
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.