2011-11-02 37 views
5

Tôi đã đọc rất nhiều bài báo, đã xem hàng tấn các chương trình truyền hình về TDD, nhưng tôi vẫn đang vật lộn với việc sử dụng nó trong dự án thế giới thực. Vấn đề chính của tôi là tôi không biết bắt đầu từ đâu, thử nghiệm nào sẽ là bài kiểm tra đầu tiên. Giả sử tôi phải viết thư viện khách hàng gọi các phương thức của hệ thống bên ngoài (ví dụ: thông báo). tôi muốn khách hàng này để làm việc như sauLàm thế nào để chọn điểm bắt đầu TDD trong một dự án thế giới thực?

NotificationClient client = new NotificationClient("abcd1234"); // client ID 
Response code = client.notifyOnEvent(Event.LIMIT_REACHED, 100); // some params of call 

Có một số dịch và thông điệp chuẩn bị định dạng đằng sau hậu trường, vì vậy tôi muốn ẩn nó từ các ứng dụng khách hàng của tôi.

Tôi không biết bắt đầu từ đâu và như thế nào. Tôi có nên tạo một số lớp học thô cho thư viện này không? Tôi nên bắt đầu với thử nghiệm NotificationClient như sau

public void testClientSendInvalidEventCommand() { 
    NotificationClient client = new NotificationClient(...); 
    Response code = client.notifyOnEvent(Event.WRONG_EVENT); 
    assertEquals(1223, code.codeValue()); 
} 

Nếu vậy, với thử nghiệm như vậy tôi buộc phải viết thực hiện làm việc hoàn chỉnh cùng một lúc, không có bước nhỏ như bang TDD. Tôi có thể thử nghiệm tính toán sosmething trong Khách hàng nhưng sau đó tôi phải biết điều này để được chế giễu trả trước, vì vậy tôi cần một số mong muốn trả trước được thực hiện.

Có lẽ tôi nên bắt đầu từ phía dưới, kiểm tra thành phần định dạng thông điệp này trước và sau đó sử dụng nó trong thử nghiệm ứng dụng khách phải không?

Cách nào phù hợp để đi? Chúng ta có nên bắt đầu từ đầu (làm thế nào để đối phó với bước tiến lớn này)? Chúng ta có thể bắt đầu với bất kỳ lớp nào thực hiện một phần nhỏ của tính năng mong muốn (như Formatter trong ví dụ này)?

Nếu tôi biết nơi để đạt được các bài kiểm tra của mình, tôi sẽ dễ dàng tiếp tục.

Trả lời

1

Đừng nhầm lẫn acceptance tests móc vào mỗi đầu của đơn đăng ký của bạn và tạo thành executable specifications với unit tests.

Nếu bạn đang thực hiện TDD thuần túy, bạn viết một bài kiểm tra chấp nhận để điều khiển các bài kiểm tra đơn vị thúc đẩy việc thực hiện. testClientSendInvalidEventCommand là bài kiểm tra chấp nhận của bạn, nhưng tùy thuộc vào những thứ phức tạp như thế nào bạn sẽ ủy thác việc triển khai cho nhiều lớp, bạn có thể kiểm tra đơn vị riêng biệt.

Những thứ phức tạp có được trước khi bạn phải phân tách chúng để kiểm tra và hiểu chúng đúng cách là lý do tại sao nó được gọi là Kiểm tra số Thiết kế.

+0

Nhưng cách tìm các lớp đó để viết các bài kiểm tra đơn vị và bắt đầu từ đâu? Tôi cho rằng tôi cần phải thiết lập một số lớp học để có thể chọn điểm bắt đầu cho TDD. Nhưng sau đó, nơi này nên được? Nó có nên ở các cạnh của hệ thống không, hoặc nó có thể ở giữa Formatter giống như hệ thống được đề cập không? –

+0

Bạn có thể TDD từ dưới lên trên hoặc từ trên xuống dưới. Tôi không thấy Formatter phù hợp với ví dụ của bạn như thế nào. Với thử nghiệm, bạn nên viết số lượng ** tối thiểu ** mã cần thiết để có được nó. –

0

Một mục tiêu của TDD là thử nghiệm thông báo cho thiết kế. Vì vậy, thực tế là bạn cần phải suy nghĩ về cách thực hiện NotificationClient của bạn là một điều tốt; nó buộc bạn phải suy nghĩ (hy vọng) trừu tượng đơn giản lên phía trước.

Ngoài ra, loại TDD giả định tái cấu trúc liên tục. Giải pháp đầu tiên của bạn có thể sẽ không phải là giải pháp cuối cùng; do đó, khi bạn tinh chỉnh mã của mình, các thử nghiệm sẽ có để cho bạn biết những gì xảy ra, từ lỗi biên dịch đến các vấn đề thời gian chạy thực tế.

Vì vậy, tôi sẽ chuyển ngay vào và bắt đầu với thử nghiệm bạn đã đề xuất. Khi bạn tạo mocks, bạn sẽ cần phải tạo các thử nghiệm cho việc triển khai thực tế những gì bạn đang chế giễu. Bạn sẽ tìm thấy những điều có ý nghĩa và cần phải được tái cấu trúc, vì vậy bạn sẽ cần phải sửa đổi các bài kiểm tra của bạn khi bạn đi. Đó là cách nó phải làm việc ...

+0

Ok, giả sử tôi đã xác định hai cộng tác viên ở đây: Trình định dạng để tạo thư ở định dạng bắt buộc và ConnectionHandler để xử lý các kết nối và gửi thư cấp thấp. Có đủ để bắt đầu thử nghiệm không? Bắt đầu từ đâu? Với thử nghiệm ConnectionHandler, hoặc Formatter? Hoặc có lẽ Khách hàng với hai người đó đã chế nhạo? –

+0

Chỉ cần chọn một hoặc khác - Tôi nghĩ rằng bạn đang ở trong phân tích tê liệt - chỉ cần làm điều đó và nó sẽ làm việc chính nó ra ... – hvgotcodes

1

Bạn có thể chọn để cho phép thử nghiệm lái xe thiết kế của bạn từ dưới lên hoặc từ trên xuống dưới. Cả hai đều hoạt động tốt cho các nhà phát triển khác nhau trong các tình huống khác nhau.Hoặc là cách tiếp cận sẽ buộc phải thực hiện một số quyết định thiết kế "trả trước" nhưng đó là một điều tốt. Làm cho những quyết định đó để viết bài kiểm tra của bạn là thiết kế dựa trên thử nghiệm!

Trong trường hợp của bạn, bạn có ý tưởng về giao diện bên ngoài cấp cao cho hệ thống bạn đang phát triển nên hãy bắt đầu ở đó. Viết một bài kiểm tra về cách bạn nghĩ rằng người dùng của ứng dụng khách thông báo của bạn nên tương tác với nó và để cho nó thất bại. Bài kiểm tra này là cơ sở cho các bài kiểm tra chấp nhận hoặc tích hợp của bạn và họ sẽ tiếp tục thất bại cho đến khi các tính năng mà họ mô tả hoàn tất. Vậy là được rồi. Bây giờ, hãy xuống một cấp. Các bước cần thực hiện để cung cấp giao diện cấp cao đó là gì? Chúng ta có thể viết một bài kiểm tra tích hợp hoặc đơn vị cho các bước đó không? Họ có phụ thuộc bạn đã không xem xét mà có thể làm cho bạn thay đổi giao diện trung tâm thông báo bạn đã bắt đầu xác định? Tiếp tục khoan xuống hành vi xác định độ sâu đầu tiên với các kiểm tra không thành công cho đến khi bạn thấy rằng bạn đã thực sự đạt đến một thử nghiệm đơn vị. Bây giờ thực hiện đủ để vượt qua bài kiểm tra đơn vị đó và tiếp tục. Nhận các bài kiểm tra đơn vị đi qua cho đến khi bạn đã xây dựng đủ để vượt qua bài kiểm tra tích hợp và v.v. Cuối cùng, bạn sẽ hoàn thành việc xây dựng một cây kiểm tra độ sâu đầu tiên và cần có một tính năng được thử nghiệm tốt có thiết kế được thúc đẩy bởi các thử nghiệm của bạn.

2

Tôi muốn bắt đầu với dòng này:

NotificationClient client = new NotificationClient("abcd1234"); // client ID 

Âm thanh như chúng ta cần một NotificationClient, mà cần một ID của khách hàng. Đó là một điều dễ dàng để kiểm tra. thử nghiệm đầu tiên của tôi có thể trông giống như:

public void testNewClientAbcd1234HasClientId() { 
    NotificationClient client = new NotificationClient("abcd1234"); 
    assertEquals("abcd1234", client.clientId()); 
} 

Tất nhiên, nó sẽ không biên dịch lúc đầu - không phải cho đến khi tôi đã viết một lớp NotificationClient với một constructor mà phải mất một tham số chuỗi và một ClientId() phương pháp đó trả về một chuỗi - nhưng đó là một phần của chu kỳ TDD.

Tại thời điểm này, tôi có thể chạy thử nghiệm và xem nó không thành công (vì tôi đã trở thành chuỗi trống của clientId() trở thành chuỗi trống). Một khi tôi đã có đơn vị kiểm tra thất bại của tôi, tôi viết vừa đủ mã sản xuất (trong NotificationClient) để có được những thử nghiệm để vượt qua:

public string clientId() { 
     return "abcd1234"; 
    } 

Bây giờ tất cả các bài kiểm tra của tôi vượt qua, vì vậy tôi có thể xem xét làm gì tiếp theo. Rõ ràng (tốt, rõ ràng để tôi) Bước tiếp theo là để đảm bảo rằng tôi có thể tạo ra khách hàng có ID không phải là "abcd1234":

public void testNewClientBcde2345HasClientId() { 
    NotificationClient client = new NotificationClient("bcde2345"); 
    assertEquals("bcde2345", client.clientId()); 
} 

tôi chạy bộ kiểm tra của tôi và nhận xét rằng testNewClientBcde2345HasClientId() thất bại trong khi testNewClientAbcd1234HasClientId() trôi qua, và bây giờ tôi đã có một lý do chính đáng để thêm một biến thành viên để NotificationClient:

public class NotificationClient { 
    private string _clientId; 
    public NotificationClient(string clientId) { 
     _clientId = clientId; 
    } 
    public string clientId() { 
     return _clientId; 
    } 
} 

Giả sử không có lỗi đánh máy đã lẻn vào, mà sẽ nhận được tất cả các xét nghiệm của tôi để vượt qua, và tôi có thể chuyển sang bất kỳ bước tiếp theo nào. (Trong ví dụ của bạn, có thể nó sẽ kiểm tra rằng notifyOnEvent(Event.WRONG_EVENT) trả về một ResponsecodeValue() bằng 1223.)

Điều đó có giúp được gì không?

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