Kiểm tra hướng phát triển: Một cách tốt / được chấp nhận để kiểm tra hoạt động của hệ thống tệp?


14

Tôi đang làm việc trên một dự án tại thời điểm tạo ra một bảng (trong số những thứ khác) dựa trên nội dung của một hệ thống tệp, và đến lượt nó thực hiện một số sửa đổi dữ liệu meta trên những thứ nó tìm thấy. Câu hỏi là: làm thế nào các bài kiểm tra nên được viết xung quanh điều này, hoặc thiết lập? Có một cách dễ dàng để chế nhạo điều này? Hay tôi nên thiết lập một "hộp cát"?

Câu trả lời:


13

Như bạn luôn làm trong TDD với các tài nguyên bên ngoài: bạn tạo một hoặc nhiều giao diện cho các hoạt động của hệ thống tệp của mình và "giả lập chúng ra". Bạn muốn kiểm tra "trình tạo bảng" và mã sửa đổi dữ liệu meta của mình, chứ không phải chính hoạt động của hệ thống tệp (rất có thể bạn đang sử dụng các triển khai thư viện được tạo sẵn để truy cập hệ thống tệp).


TDD không khuyến nghị chế giễu việc thực hiện đơn vị đang thử nghiệm. Xem (e, g) solnic.eu/2014/05/22/mocking-and-ruby.html
soru

1
@soru: Đó không phải là những gì câu trả lời này đề nghị. Nó khuyến nghị đầu tiên tạo giao diện, sau đó chế nhạo giao diện . Vì vậy, bạn kiểm tra logic nghiệp vụ, nhưng không phải giao diện hệ thống tập tin.
sleske

5
Nhưng có vẻ như logic kinh doanh được xác định theo các tệp và thư mục. Vì vậy, thứ gọi API hệ thống tệp thứ cần kiểm tra. Kiểm tra bất kỳ logic kinh doanh phi tập tin liên quan không cần chế nhạo; Chỉ cần kiểm tra nó.
soru

@soru đúng, vì vậy bạn tạo một lớp mỏng xung quanh các tệp và thư mục với giao diện được xác định sao cho tất cả các hoạt động cụ thể của miền nằm ở phía máy khách và phía triển khai đủ tầm thường để tự tin hoạt động mà không cần kiểm tra đơn vị (kiểm tra tích hợp sẽ vẫn được yêu cầu). Tương tự như ý tưởng về Hộp thoại khiêm tốn trong mã ui hoặc sử dụng Kho lưu trữ giả trong mã hoạt động trên các đối tượng liên tục.
Jules

2
Vì vậy, chúng tôi từ bỏ việc kiểm tra lớp thực tế tương tác với hệ thống tệp, cơ sở dữ liệu, v.v ... thay vào đó chúng tôi tạo ra một triển khai khác với cùng giao diện như một mock / stub, nhưng lớp thực tế chúng tôi rời khỏi mà không có bất kỳ loại thử nghiệm đơn vị nào, bởi vì chúng tôi tin rằng chúng tôi không thể kiểm tra đơn vị và nên thực hiện kiểm tra tích hợp để kiểm tra thay thế. Điều này có đúng không?
Andrew Savinykh

11

Có gì sai khi có một hệ thống tập tin "thử nghiệm"?

Tạo một cấu trúc thư mục / thư mục mẫu có đủ nội dung để kiểm tra các hoạt động của bạn.

Trong quá trình thiết lập thử nghiệm đơn vị của bạn, sao chép cấu trúc ban đầu này (sẽ khuyên bạn nên ZIP mẫu và giải nén vào khu vực thử nghiệm của bạn). Chạy thử nghiệm của bạn. Xóa toàn bộ trong khi xé xuống.

Vấn đề với việc chế nhạo trước hết là các hệ thống tệp, HĐH và cơ sở dữ liệu thuộc dự án của bạn không thực sự đủ điều kiện là tài nguyên bên ngoài và thứ hai là chế nhạo các cuộc gọi hệ thống cấp thấp vừa tốn thời gian vừa dễ bị lỗi.


5
Việc loại bỏ các hoạt động của hệ thống tệp sẽ tạo ra các thử nghiệm chạy nhanh hơn nhiều (!) So với sử dụng hệ thống tệp thực và nếu điều này dễ bị "lỗi" hơn, tôi sẽ nói rằng nó phụ thuộc vào việc triển khai. Tuy nhiên, tôi nghĩ rằng đề xuất của bạn là tốt để tạo các bài kiểm tra tích hợp tự động (điều mà tôi thường làm trước tiên khi không làm TDD). Nhưng OP đặc biệt yêu cầu TDD, và các bài kiểm tra đơn vị TDD phải nhanh chóng.
Doc Brown

1
Tôi nghĩ rằng các hệ thống tệp, nếu bị chế giễu, lý tưởng nhất là phải có toàn bộ API được viết và duy trì bởi một nhóm, bởi vì bạn đang phát minh lại bánh xe, nếu bạn làm bất cứ điều gì có ý nghĩa với hệ thống tệp.
Frank Hileman

2
@Doc Brown - Tôi giả sử rằng anh ta muốn thực hiện dir, xóa và đổi tên các hoạt động loại tất cả đều có các trường hợp cạnh sẽ gây đau đớn khi chế nhạo. Ngoài ra, trên phần cứng hiện đại, việc giải nén một vài tệp nhỏ vào một thư mục chỉ chậm hơn một chút so với việc tải một lớp Java - tất cả đều là IO.
James Anderson

Tôi càng nghĩ về hệ thống tập tin thử nghiệm, tôi càng thích nó.
Frank Hileman

3

Đây là loại điều bạn chắc chắn cần kiểm tra tích hợp, vì các hệ thống tệp trong thế giới thực có tất cả các loại hành vi lạ (như cách Windows sẽ không cho phép xóa tệp nếu bất kỳ quy trình nào, bao gồm cả trình duyệt, mở nó).

Vì vậy, cách tiếp cận TDD là viết thử nghiệm tích hợp trước tiên (TDD, nói đúng ra, không có khái niệm riêng biệt về 'thử nghiệm đơn vị' và 'thử nghiệm tích hợp'; chúng chỉ là thử nghiệm). Rất có khả năng đó sẽ là đủ; Thế là xong việc, dừng lại, về nhà .

Nếu không, sẽ có một số phức tạp bên trong không dễ kiểm tra đầy đủ bằng cách sắp xếp các tệp. Trong trường hợp đó, bạn chỉ cần lấy sự phức tạp đó ra, đặt nó vào một lớp và viết các bài kiểm tra đơn vị cho lớp đó . Rất có khả năng bạn sẽ thấy rằng lớp chung có thể sử dụng được trong các trường hợp cơ sở dữ liệu, tệp xml, v.v.

Trong mọi trường hợp, bạn sẽ lấy lõi cơ bản của mã bạn đang viết và 'giả' nó ra để viết các bài kiểm tra sẽ vượt qua liệu đơn vị được kiểm tra có sai hay không.


Câu trả lời này thực sự đặt nó vào viễn cảnh đối với tôi - 'unit test' and 'integration test'; they are just tests.tôi nghĩ thực tế, đây sẽ là giải pháp tốt nhất cho trường hợp của tôi - Tôi thực sự cần kiểm tra các thư viện hệ thống tệp tôi đang sử dụng cho các trường hợp cạnh và cách ứng dụng nên phản hồi những, cái đó. Nếu tôi chuyển sang thư viện hệ thống tệp khác, tôi không muốn phải viết lại một loạt các mã giả / mã kiểm tra để làm việc với thư viện mới, nhưng có cấu trúc thư mục kiểm tra và kiểm tra tích hợp sẽ đơn giản hơn nhiều.
tehDorf

2

Tôi hiểu câu hỏi của bạn là "Cách tốt / được chấp nhận để kiểm tra một lớp phụ thuộc vào hoạt động của hệ thống tệp". Tôi không cho rằng bạn muốn kiểm tra hệ thống tập tin của hệ điều hành của bạn.

Để duy trì nỗ lực 'giao diện cho các hoạt động của hệ thống tệp của bạn và "giả lập chúng" "như câu trả lời @Doc Brown đề xuất càng nhỏ càng tốt, nên sử dụng luồng nhị phân java hoặc trình đọc văn bản (hoặc tương đương trong c # hoặc ngôn ngữ lập trình bạn đang sử dụng) thay vì sử dụng Tệp có tên tệp trực tiếp trong lớp do bạn phát triển.

Thí dụ:

Sử dụng java Tôi đã triển khai một lớp CsvReader

public class CsvReader {
    private Reader reader;

    public CsvReader(Reader reader) {
        this.reader = reader;
    }
}

Để kiểm tra tôi đã sử dụng dữ liệu bộ nhớ như thế này

String contentOfCsv = "TestColumn1;TestColumn2\n"+
    "value1;value2\n";

CsvReader sut = new CsvReader(java.io.StringReader(contentOfCsv));

hoặc đưa testdata vào tài nguyên

CsvReader sut = new CsvReader(getClass().getResourceAsStream("/data.csv"));

Trong sản xuất tôi sử dụng hệ thống tập tin

CsvReader sut = new CsvReader(new BufferedReader( new FileReader( "/import/Prices.csv" ) ));

Bằng cách này, CsvReader của tôi không phụ thuộc vào hệ thống tệp mà phụ thuộc vào "Trình đọc" trừu tượng, nơi có triển khai cho hệ thống tệp.


2
Vấn đề duy nhất ở đây là OP không nói về hoạt động của tệp, mà là hoạt động của hệ thống tệp và thao tác dữ liệu meta - Tôi đoán anh ta có ý gì đó như liệt kê tất cả các tệp trong một thư mục, cập nhật một số thông tin EXIF ​​trong tất cả các tệp ảnh, v.v.
Doc Brown

Chính xác.
Kirbinator

1
Bạn có thể tạo IDirectoryLister có phương thức String [] List (thư mục String); sau đó FakeDirectoryLister có thể thực hiện phương thức đó bằng cách trả về Chuỗi mới [] {".", "..", "foo.bat", "bar.exe"};
Anders Lindén

0

Tạo một trình bao bọc cho các hoạt động hệ thống tập tin. Trong các thử nghiệm, vượt qua trong một bản giả thực hiện giao diện giống như trình bao bọc. Trong sản xuất, vượt qua trong bọc.

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.