TDD, thử nghiệm mới trong khi thử nghiệm cũ chưa được thực hiện


13

Tôi đang thử nghiệm phát triển dựa trên thử nghiệm và tôi thấy rằng tôi thường gặp phải một tình huống sau:

  1. Tôi viết bài kiểm tra cho một số chức năng X. Những bài kiểm tra thất bại.
  2. Trong khi thử triển khai X, tôi thấy rằng tôi cần triển khai một số tính năng Y ở lớp dưới của mã. Vì thế...
  3. Tôi viết bài kiểm tra cho Y. Bây giờ cả hai bài kiểm tra cho X và Y đều thất bại.

Khi tôi có 4 tính năng trong các lớp mã khác nhau được thực hiện cùng một lúc và tôi đã mất tập trung vào những gì tôi thực sự đang làm (quá nhiều thử nghiệm thất bại cùng một lúc).

Tôi nghĩ rằng tôi có thể giải quyết điều này bằng cách nỗ lực nhiều hơn vào việc lập kế hoạch cho các nhiệm vụ của mình ngay cả trước khi tôi bắt đầu viết bài kiểm tra. Nhưng trong một số trường hợp, tôi không biết rằng mình sẽ cần phải đi sâu hơn, vì ví dụ tôi không biết rõ về API của lớp thấp hơn.

Tôi nên làm gì trong những trường hợp như vậy? TDD có khuyến nghị nào không?

Câu trả lời:


9

Điều tốt là bạn nhận ra mã của mình dưới sự kiểm tra cần hỗ trợ. Thay vì triển khai nó ngay lập tức, hãy tạo một giao diện và sử dụng các giả để đảm bảo các bài kiểm tra của bạn đang gắn thẻ đúng mã. Sau khi bạn vượt qua các bài kiểm tra đó, bạn có thể chuyển sang thực hiện mã mà nó dựa vào.


Các thử nghiệm của tôi thường không có kiến ​​thức về phương pháp nên làm gì trong nội bộ (nên gọi API cấp thấp hơn). Tôi có nên điều chỉnh các bài kiểm tra để giả lập bất cứ điều gì tôi cần trong mã được kiểm tra không?
liori

2
Tương tự, các lớp được kiểm tra của bạn không nên quan tâm 'lớp dưới' làm gì. Sử dụng giả / sơ khai thay cho các lớp / đối tượng thực tế. Điều này có thể đòi hỏi một chút nỗ lực hơn trong thiết kế, nhưng kết quả là mã ít được ghép nối và dễ sử dụng hơn.
Mchl

1
Bạn đang sử dụng tiêm phụ thuộc? Đây là cách bạn có thể dễ dàng tách các mối quan tâm cấp thấp hơn khỏi các lớp cấp cao hơn. Lớp của bạn đang kiểm tra có một hàm tạo với các tham số cho các phụ thuộc của nó (dưới dạng các giao diện) trong thử nghiệm của bạn, bạn tạo các giả cho các giao diện. Về cơ bản, bạn đang giả vờ rằng bạn đã triển khai các dịch vụ cấp thấp hơn.
Michael Brown

@Mike Brown, vâng, tôi làm. Tôi biết tôi có thể tạo các đối tượng giả. Nhưng sau đó, trong thử nghiệm tính năng của Xtôi, tôi phải biết phần nào của sự phụ thuộc của Xtôi cần phải chế giễu. Tôi cảm thấy rằng đây là một phần của chi tiết triển khai, không phải là một phần của các thử nghiệm - nếu không tôi có thể cần phải thay đổi các thử nghiệm trong khi tái cấu trúc việc thực hiện. Tôi có nên lo lắng về điều đó?
liori

1
Hoàn toàn không ... các bài kiểm tra sẽ phản ánh các giả định của hệ thống được kiểm tra. Nó cũng giúp bạn tiết lộ những gì bạn cần từ các dịch vụ mà hệ thống dựa vào. Tôi đã từng đồng ý với bạn về vấn đề này nhưng tôi so sánh nó với cách tôi hiểu về lập trình đệ quy. Đầu tiên bạn viết mã giả sử rằng bạn có một hàm thực hiện những gì bạn muốn. Sau đó, bạn viết mã mà làm những gì bạn muốn.
Michael Brown

4

Sơ khai và giả có thể được sử dụng để mô phỏng chức năng chưa được sửa đổi / triển khai. Họ cũng có thể giúp bạn giải quyết các phụ thuộc gây ra loại 'phản ứng dây chuyền' này.

Mặt khác, có lẽ chỉ giữ một thử nghiệm (thất bại) thúc đẩy thay đổi tiếp theo là cách tiếp cận tốt nhất.

Các thử nghiệm khác nhắm vào mã dựa trên chức năng mới có thể bị vô hiệu hóa tạm thời vì chúng không thực sự phù hợp vào thời điểm này. trong trường hợp của bạn, hãy vô hiệu hóa các kiểm tra cho X cho đến khi bạn triển khai Y, v.v.

Bằng cách đó, bạn có thể tập trung vào thay đổi tiếp theo, đó là điều bạn muốn, tôi nghĩ vậy.


Ha, tôi đã tìm một tính năng để tắt một bài kiểm tra trong quá trình chạy thử bên trong IDE của tôi và không tìm thấy một tính năng nào. Bây giờ tôi thấy rằng trăn unittestđã bỏ qua thử nghiệm. Điều này có thể là đủ cho tôi.
liori

Chúng tôi sử dụng google test C ++ framework - và nó có một tùy chọn để vô hiệu hóa các bài kiểm tra. Các thử nghiệm bị vô hiệu hóa không được thực thi nhưng được biên dịch - thời điểm bạn cần chúng - chúng sẵn sàng để chạy (ngoài ra bạn có thể 'buộc thực thi' các thử nghiệm bị vô hiệu hóa - loại 'kích hoạt thời gian chạy') - tính năng tuyệt vời ...
ratkok

3

Dừng lại

Có vẻ như có thể có hai vấn đề riêng biệt ở đây:

  1. bạn đã quên một số câu chuyện và kịch bản thử nghiệm và không khám phá chúng cho đến khi bạn bắt đầu thực hiện một kịch bản thử nghiệm cụ thể và / hoặc

  2. bạn thực sự đang thực hiện kiểm tra đơn vị chứ không phải kiểm tra tính năng TDD

Đối với # 1, dừng lại , quay lại và cập nhật các câu chuyện và kịch bản thử nghiệm, sau đó bắt đầu lại với một kịch bản khác.

Đối với # 2, hãy dừng lại và nhớ rằng bạn đang thử nghiệm các tính năng, không phải đơn vị, vì vậy hãy sử dụng giả để làm bóng trên các giao diện khác và / hoặc triển khai thêm mã để thực hiện kiểm tra mà không cần thêm các kịch bản thử nghiệm mới. Điều này giả định rằng bạn không thiếu các kịch bản thử nghiệm, nhưng thay vào đó - và điều này thực sự phổ biến - thử nghiệm đơn vị kết hợp và TDD.


Tôi thực sự thích câu trả lời của bạn, nó làm tốt hơn việc giải thích những gì đang thực sự xảy ra.
maple_shaft

... Với điều đó được nói rằng tôi không biết một Thủ tướng trên thế giới, người sẽ không hoàn toàn đánh mất lý trí của mình với câu "DỪNG LẠI, chúng ta cần quay lại". Họ sẽ cố gắng hết sức để hy sinh đứa con đầu lòng của mình tại bàn thờ để giữ cho dự án tiến lên, nợ kỹ thuật và các bài kiểm tra đơn vị không đầy đủ bị nguyền rủa. Tôi đoán bạn không thể đổ lỗi cho họ khi số liệu duy nhất của họ tại một tổ chức đang hoàn thành dự án đúng hạn. Một số tổ chức chỉ coi trọng thời gian hơn chất lượng và đây là lý do tại sao tôi có thể chưa bao giờ thấy TDD hoạt động thành công tại các loại tổ chức này, điều không may là NHIỀU trong số họ IMO.
maple_shaft

@maple_shaft: lượng thời gian bạn dừng để tập hợp lại có thể chỉ là một vài giờ - trừ khi quá trình của bạn diễn ra, rời khỏi cơ sở, trong trường hợp dừng lại vài ngày để đưa nó trở lại đúng hướng sẽ khiến nó có nhiều khả năng dự án sẽ thành công. Không có điểm nào đi hết hơi trước khi đi sai đường!
Steven A. Lowe

0

Đây là một câu hỏi hay và một sự thất vọng lớn đối với tôi cũng như với TDD. Tôi cảm thấy như TDD thiếu trong kịch bản này khi bạn không có cách nào để biết các thành phần hoặc tính năng cấp thấp hơn bạn sẽ cần cho đến khi bạn bắt đầu phát triển.

Cá nhân tôi thấy rằng TDD chỉ hoạt động nếu bạn biết chính xác những gì bạn cần làm và những gì bạn cần gọi để thực hiện một tính năng. Các nhà phát triển không phải lúc nào cũng biết mọi thứ trước khi chúng tôi bắt đầu, vì vậy tôi đã thấy rằng cách tốt nhất cho bản thân để giảm thiểu chính tình huống mà bạn mô tả:

Nguyên mẫu

Khi tôi tạo các ứng dụng nguyên mẫu đơn giản để khám phá và khám phá các phương pháp và cách tiếp cận với một vấn đề kỹ thuật thì tôi phát hiện ra rất nhiều công việc chân và đưa nghiên cứu đó ra khỏi đường trước khi tôi bắt đầu. Thiết kế và ước tính cũng trở nên dễ dàng hơn rất nhiều.

Nếu nguyên mẫu phải liên quan đến mức nó trở thành ứng dụng thì tôi khuyên bạn không nên làm điều lười biếng tuy nhiên và xây dựng các bài kiểm tra đơn vị cho nguyên mẫu của bạn sau khi thực tế.

Bạn nên biết thêm về API cấp thấp hơn tại thời điểm đó và có thể giả định thành công API cấp thấp hơn trong các thành phần cấp cao hơn của bạn.


Vì vậy, bạn thực sự đang đề xuất để có thêm thông tin cho giai đoạn lập kế hoạch bằng cách thực hiện một số mã hóa khám phá theo cách không chính thức (= không đi theo một phương pháp chính thức). Và sau đó giả định rằng nó sẽ cung cấp đủ thông tin để lập kế hoạch mã thực. Tôi có đúng không
liori

Tại sao bạn cho rằng tạo mẫu là một quá trình không chính thức? Mọi ước tính nên chiếm nguyên mẫu và lịch trình dự án nên chiếm nó cũng như một nhiệm vụ phát triển cần thiết. Tôi xem nó giống như Thiết kế hoặc Đánh giá mã. Trên lưu ý đó, nó được chính thức hóa và nên được tính đến, thậm chí nhiều hơn về các nhiệm vụ với rất nhiều điều chưa biết. Không có nguyên mẫu và khả năng thực hiện Proof-of-Concept, sau đó theo đuổi TDD chỉ giả định rằng các nhà phát triển biết MỌI THỨ về MỌI THỨ với TẤT CẢ các tính năng. Thế giới thực không hoạt động theo cách đó và tôi không quan tâm bạn thông minh hay có kinh nghiệm như thế nào.
maple_shaft

Theo "cách không chính thức" tôi không có nghĩa là không nên tính đến thời gian tạo mẫu, nhưng trong khi bạn làm nguyên mẫu, bạn không tuân theo TDD hoặc bất kỳ phương pháp mã nào khác.
liori

TDD là một phương pháp để kiểm tra và phát triển đơn vị. Sẽ có ý nghĩa khi làm TDD cho Đánh giá mã? TDD có ý nghĩa đối với Thiết kế, viết Thông số kỹ thuật hoặc Bảng trắng không? Tạo mẫu là một nhiệm vụ của chính nó, một kiểu phát triển khám phá cho nghiên cứu, bằng chứng về khái niệm và giáo dục.
maple_shaft

1
TDD có ý nghĩa hoàn hảo cho tạo mẫu. Nó cho phép bạn nhanh chóng phơi bày những thứ mà bạn đang có (đối tượng, chức năng, API, toàn bộ chương trình) dưới dạng một bộ yêu cầu có thể lặp lại, có thể thực hiện được. Tự mình làm và đọc phần mềm hướng đối tượng phát triển được hướng dẫn bởi các bài kiểm tra ; nó sẽ đưa bạn từng bước thông qua việc xây dựng toàn bộ ứng dụng (bao gồm tích hợp) theo cách thử nghiệm đầu tiên.
Frank Shearar

0

Nó phụ thuộc vào loại bài kiểm tra viết của bạn trong khi làm TDD.

Mô hình cổ điển là viết các bài kiểm tra đơn vị và sử dụng các giả hoặc sơ khai để tách bài kiểm tra khỏi các "đơn vị" mã khác.

Có nhiều mô hình thay thế khác như ATDD trong đó kiểm tra một ngăn xếp đầy đủ hoặc kiểm tra ngăn xếp gần như đầy đủ. Trong trường hợp cụ thể này, các bài kiểm tra viết của bạn khẳng định hành vi chương trình yêu cầu không phải là một đơn vị mã, do đó bạn sẽ không viết các bài kiểm tra khác. Bạn sẽ nhận được việc thực hiện roundtrip để đáp ứng bài kiểm tra. Sau đó, bạn thêm các thử nghiệm khác cho các tính năng / hành vi khá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.