2010-03-17 27 views
14

Câu hỏi rất cụ thể từ người mới đến TDD:Quá nhiều phương pháp công cộng bị bắt buộc bởi phát triển thử nghiệm theo hướng

Tôi tách riêng các thử nghiệm và ứng dụng của mình thành các gói khác nhau. Do đó, hầu hết các phương pháp ứng dụng của tôi phải được công khai để kiểm tra truy cập chúng. Khi tôi tiến bộ, rõ ràng là một số phương pháp có thể trở thành riêng tư, nhưng nếu tôi thực hiện thay đổi đó, các thử nghiệm truy cập chúng sẽ không hoạt động. Tôi đang thiếu một bước, hoặc làm điều gì đó sai trái, hay đây chỉ là một sự sụp đổ của TDD?

+0

tôi nghĩ bạn sẽ muốn thử nghiệm trong cùng một "đơn vị tệp mã" như những thứ đang được thử nghiệm. Bằng cách đó họ có quyền truy cập vào ruột. –

+0

Là một newd TDD tôi vẫn còn bị nhầm lẫn bởi các chỉ thị TDD kép: "không viết một dòng mà không kiểm tra" và "không kiểm tra nội bộ". Nếu cả hai đều được theo sau nó ngụ ý rằng mọi thứ bắt đầu công khai nhưng trở thành riêng thông qua tái cấu trúc và chỉ thông qua tái cấu trúc. Khi bạn thực hiện việc tái cấu trúc đó, bạn có thể chắc chắn rằng bạn chỉ đơn thuần là tìm kiếm mã đã được thử nghiệm thành một cấu hình mã khác. Cho đến nay, rất khó hiểu. Nhưng sự gãi đầu thực sự xảy ra khi bạn chấp nhận chỉ thị thiêng liêng thứ ba: "không bao giờ đưa ra phương thức công khai chỉ cho mục đích thử nghiệm". –

Trả lời

18

Đây không phải là một sự sụp đổ của TDD, mà là một cách tiếp cận để kiểm tra tin rằng bạn cần kiểm tra mọi thuộc tính và mọi phương pháp. Trong thực tế, bạn không nên quan tâm đến các phương thức riêng khi thử nghiệm vì chúng chỉ nên tồn tại để tạo điều kiện cho một số phần công cộng của API.

Không bao giờ thay đổi điều gì đó từ riêng tư thành công khai cho mục đích thử nghiệm!

Bạn chỉ nên cố gắng xác minh hành vi hiển thị công khai. Phần còn lại là các chi tiết triển khai và bạn đặc biệt muốn tránh kiểm tra các chi tiết đó. TDD có nghĩa là để cung cấp cho bạn một bộ các bài kiểm tra sẽ cho phép bạn dễ dàng thay đổi các chi tiết thực hiện mà không vi phạm các bài kiểm tra (hành vi thay đổi).

Cho phép nói rằng tôi có loại: MyClass và tôi muốn thử nghiệm phương pháp DoStuff. Tất cả những gì tôi quan tâm là phương thức DoStuff có ý nghĩa gì đó và trả về kết quả mong đợi. Nó có thể gọi một trăm phương pháp riêng tư để đạt được điểm đó, nhưng tôi không quan tâm như người tiêu dùng của phương pháp đó.

+4

Nhưng bạn ** muốn ** một cách để kiểm tra hàng trăm phương thức nội bộ đó, phải không? –

+4

@Ian - Nếu bạn đang thực hiện TDD, thì chúng đã được kiểm tra rồi. Sự tồn tại của chúng có nghĩa là chúng được đặt ở đó để thực hiện một phép thử. Tuy nhiên, những phương pháp đó là một chi tiết triển khai mà người tiêu dùng không nên biết đến. Nếu tôi tìm ra sau đó tôi có thể cấu trúc lại 100 phương pháp đó thành 50 phương pháp, tôi không cần phải viết lại các bài kiểm tra của mình. Vì vậy ... có bạn kiểm tra chúng, nhưng không trực tiếp bởi vì bạn chỉ quan tâm đến API công khai. Nếu có một số phương pháp riêng tư không thể thực hiện thông qua API công khai, thì nó là vô dụng và cần được loại bỏ. – Josh

+0

Tôi đang theo dõi Hướng dẫn Thực hành của David Astels - ông chỉ ra rằng bạn thử nghiệm những thứ đó và sau đó refactor khi có quá nhiều sự thân mật - điều đó sẽ khiến tôi thay đổi rất nhiều phương thức từ công khai thành riêng tư (không riêng tư) refactor các xét nghiệm của tôi thiết lập để loại bỏ những người không còn thử nghiệm hành vi công cộng - điều này có hợp lý không? – RoryG

9

Bạn không chỉ định ngôn ngữ bạn đang sử dụng, nhưng chắc chắn trong hầu hết các bạn có thể đặt các bài kiểm tra theo cách có quyền truy cập đặc quyền hơn vào lớp. Trong Java, ví dụ, kiểm thử có thể nằm trong cùng một gói, với tệp lớp thực tế nằm trong một thư mục khác, do đó nó tách biệt với mã sản xuất.

Tuy nhiên, khi bạn đang thực TDD, các bài kiểm tra sẽ hướng thiết kế lớp, vì vậy nếu bạn có phương pháp chỉ để kiểm tra một số chức năng, bạn có thể (không phải lúc nào) làm điều gì đó sai, và bạn nên xem xét kỹ thuật như tiêm phụ thuộc và chế nhạo để hướng dẫn thiết kế của bạn tốt hơn.

+3

Tôi đã gặp một vấn đề tương tự trong C# một thời gian trước - trong ngôn ngữ/khung công tác đó, bạn muốn chỉ thị 'InternalsVisibleTo'. – Tim

1

Ít nhất trong Java, thực hành tốt là có hai cây nguồn, một cho mã và một cho thử nghiệm. Vì vậy, bạn có thể đặt mã và các thử nghiệm của mình trong cùng một gói, trong khi chúng vẫn nằm trong các thư mục khác nhau:

src/org/my/xy/X.java 
test/org/my/xy/TestX.java 

Sau đó, bạn có thể đặt gói phương thức riêng tư.

+0

Tôi băn khoăn về điều này ... nhưng, theo các cuốn sách (ví dụ: Phát triển phần mềm OO được hướng dẫn bởi kiểm thử), thực hành tốt nhất là áp dụng hệ thống phân cấp thư mục dựa trên loại bài kiểm tra, (ví dụ: kiểm tra đơn vị, kiểm tra chức năng, kết thúc kiểm tra -to-end) ... phát nổ khả năng sử dụng gói riêng tư. Tôi đi đến kết luận rằng bạn phải thả nó như là chiến lược ... (mặc dù tôi là một newd TDD :)) –

+0

@mike gặm nhấm: Bạn vẫn có thể sử dụng "unit-test/org/my/xy/UnitTestX.java "và" functional-test/org/my/xy/FunctionalTestX.java ". Hơn nữa, nó có thể không cần thiết để truy cập mã gói riêng bởi _all_ các loại kiểm tra. –

7

Đây là câu nói cũ, "TDD là về thiết kế", thường xuyên xuất hiện. Một lớp học với quá nhiều phương pháp công cộng có thể có quá nhiều trách nhiệm - và thực tế là bạn đang lái thử, nó chỉ phơi bày điều đó; nó không gây ra vấn đề.

Khi bạn thấy mình trong tình huống này, giải pháp tốt nhất là thường xuyên tìm một số tập con của phương thức công khai có thể được trích xuất vào một lớp mới ("lớp mầm"), sau đó cho lớp ban đầu của bạn một biến mẫu của lớp nảy mầm. Các phương thức công khai xứng đáng được công khai trong lớp mới, nhưng bây giờ chúng - đối với API của lớp gốc - riêng tư. Và bây giờ bạn đã tuân thủ tốt hơn với SRP, khớp nối lỏng hơn, sự gắn kết thấp hơn - thiết kế tốt hơn.

Tất cả vì các tính năng tiếp xúc của TDD trong lớp học của bạn mà nếu không sẽ bị trượt dưới radar. TDD về Thiết kế.

+0

Điều này có ý nghĩa rất nhiều. Nếu chỉ có một cuốn sách thực sự đã đưa bạn bằng tay và cho bạn thấy làm thế nào để hiểu "mùi thiết kế" của loại bạn cần để phát triển độ nhạy cho TDD. Học hỏi từ (cay đắng) kinh nghiệm có giá trị của nó, nhưng nó không phải là một nửa thời gian. –

Các vấn đề liên quan