2008-09-15 23 views
16

Tôi vừa mới bắt đầu viết các bài kiểm tra đơn vị cho một mô-đun mã kế thừa với các phụ thuộc vật lý lớn bằng cách sử dụng lệnh #include. Tôi đã đối phó với họ một vài cách cảm thấy quá tẻ nhạt (cung cấp các tiêu đề rỗng để phá vỡ danh sách phụ thuộc dài và sử dụng #define để ngăn các lớp được biên dịch) và đang tìm kiếm một số chiến lược tốt hơn để xử lý các vấn đề này.C++ Đơn vị kiểm tra Mã kế thừa: Cách xử lý #include?

Tôi thường xuyên gặp phải sự cố sao chép hầu hết mọi tệp tiêu đề với phiên bản trống để tách lớp tôi đang thử nghiệm toàn bộ và sau đó viết mã gốc/mock/mã giả cho các đối tượng sẽ cần được thay thế vì chúng hiện không được xác định.

Bất kỳ ai cũng biết một số phương pháp hay hơn?

+0

Tôi ước tôi có thể nâng cấp này lên x 10, đây là câu hỏi hay nhất về SO mà tôi đã đọc cho đến nay. Tôi đã mất số lượng những người chỉ từ bỏ 'Chúng tôi không thể kiểm tra .. chúng tôi có mã C++ .. Boohoo!' – Gishu

+0

Gishu, Không thể đồng ý hơn. Tôi đang có những cuộc thảo luận tương tự ở đây, nơi tôi làm việc. – Lou

Trả lời

9

Sự trầm cảm trong các câu trả lời là áp đảo ... Nhưng đừng lo, chúng tôi có the holy book to exorcise the demons of legacy C++ code. Nghiêm túc chỉ cần mua cuốn sách nếu bạn đang xếp hàng trong hơn một tuần kể từ khi bắt đầu với mã C++ kế thừa.

Chuyển đến trang 127: Trường hợp phụ thuộc khủng khiếp bao gồm phụ thuộc. (Bây giờ tôi thậm chí không trong vòng dặm của Feathers Michael nhưng ở đây như ngắn-như-I-thể-quản lý câu trả lời ..)

Vấn đề: Trong C++ nếu classA cần biết về ClassB, Class B khai báo là thẳng-up/văn bản bao gồm trong tập tin nguồn của ClassA. Và kể từ khi chúng tôi lập trình thích đưa nó đến cùng cực, một tập tin có thể đệ quy bao gồm một tỷ người khác quá cảnh. Xây dựng mất nhiều năm .. nhưng hey atleast nó xây dựng .. chúng ta có thể chờ đợi.

Bây giờ, để nói 'việc phân loại ClassA ngay lập tức dưới sự khai thác thử nghiệm là khó khăn' là một cách nói. (Trích dẫn ví dụ của MF - Trình lập lịch biểu là đứa trẻ có vấn đề về poster của chúng tôi với số lượng lớn.)

#include "TestHarness.h" 
#include "Scheduler.h" 
TEST(create, Scheduler)  // your fave C++ test framework macro 
{ 
    Scheduler scheduler("fred"); 
} 

Điều này sẽ đưa ra con rồng kèm theo lỗi xây dựng. Thổi # 1 Kiên nhẫn-n-Persistence: Đưa vào mỗi lần đưa vào một lần và quyết định xem chúng tôi có thực sự cần sự phụ thuộc đó hay không. Giả sử SchedulerDisplay là một trong số chúng, có phương thức displayEntry được gọi trong ctor của Scheduler.
Blow # 2 Fake-it-đến-bạn-make-nó (Cảm ơn RonJ):

#include "TestHarness.h" 
#include "Scheduler.h" 
void SchedulerDisplay::displayEntry(const string& entryDescription) {} 
TEST(create, Scheduler) 
{ 
    Scheduler scheduler("fred"); 
} 

Và pop đi sự phụ thuộc và tất cả bắc cầu của nó bao gồm. Bạn cũng có thể sử dụng lại các phương thức Fake bằng cách đóng gói nó trong tệp Fakes.h để đưa vào các tệp thử nghiệm của bạn.
Thổi # 3 Thực hành: Có thể không phải lúc nào cũng đơn giản .. nhưng bạn có ý tưởng. Sau vài cuộc quyết đấu đầu tiên, quá trình DEPS vi phạm sẽ được dễ dàng-n-cơ khí

Hãy cẩn thận (Ý của tôi đề cập có nhiều tiền đề? :)

  • Chúng ta cần một xây dựng riêng cho các trường hợp thử nghiệm trong tập tin này; chúng ta chỉ có thể có 1 định nghĩa cho phương thức SchedulerDisplay :: displayEntry trong một chương trình.Vì vậy, hãy tạo một chương trình riêng cho các bài kiểm tra lên lịch.
  • Chúng tôi không vi phạm bất kỳ phụ thuộc nào trong chương trình, vì vậy chúng tôi không làm cho trình dọn dẹp mã.
  • Bạn cần phải duy trì những hàng giả đó miễn là chúng tôi cần thử nghiệm.
  • cảm giác của bạn về thẩm mỹ có thể bị xúc phạm trong một thời gian .. chỉ cắn môi của bạn và 'gấu với chúng tôi để một ngày mai tốt hơn'

Sử dụng kỹ thuật này cho một lớp học rất lớn với các vấn đề phụ thuộc nặng. Không sử dụng thường xuyên hoặc nhẹ nhàng .. Sử dụng điểm này làm điểm bắt đầu để tái cấu trúc lại sâu hơn. Theo thời gian, chương trình thử nghiệm này có thể được thực hiện phía sau chuồng khi bạn trích xuất nhiều lớp hơn (VỚI các bài kiểm tra của riêng chúng).

Để biết thêm .. vui lòng đọc sách. Vô giá. Chiến đấu trên bro!

+0

Trong khi tôi thấy đây là một câu trả lời có thể chấp nhận được, tôi cảm thấy nó thực sự đánh bóng quá trình giữa việc cung cấp sơ khai giả trong việc thực hiện chức năng thay thế và ma thuật đã được tạo sẵn trong quá trình xây dựng. – MasD

1

Vì bạn đang thử nghiệm mã di sản tôi giả sử bạn không thể cấu trúc lại cho biết mã để có phụ thuộc ít hơn (ví dụ bằng cách sử dụng các pimpl idiom)

Vậy là bạn với các tùy chọn ít Tôi sợ. Mỗi tiêu đề đã được bao gồm cho một loại hoặc chức năng sẽ cần một đối tượng giả cho loại hoặc chức năng đó cho tất cả mọi thứ để biên dịch, có rất ít bạn có thể làm ...

0

Nếu bạn tiếp tục viết stubs/mock/mã giả mạo bạn có nguy cơ làm kiểm tra đơn vị trên một lớp có hành vi khác nhau sau đó khi được biên dịch trên dự án chính.

Nhưng nếu chúng bao gồm ở đó và không có hành vi được thêm thì Ok.

Tôi sẽ cố gắng không thay đổi bất kỳ thứ gì trong phần bao gồm trong khi thực hiện thử nghiệm đơn vị để bạn chắc chắn (bạn có thể ở trên mã cũ :)) mà bạn thử nghiệm mã thực.

1

Tôi không trả lời câu hỏi của bạn trực tiếp nhưng tôi e rằng thử nghiệm đơn vị chỉ có thể không phải là điều cần làm nếu bạn làm việc với số lượng lớn mã cũ.

Sau khi dẫn đầu một nhóm XP trong một dự án phát triển lĩnh vực màu xanh lá cây, tôi thực sự yêu các bài kiểm tra Đơn vị của mình. Những điều đã xảy ra và một vài năm sau, tôi thấy mình làm việc trên một cơ sở mã di sản lớn có rất nhiều vấn đề về chất lượng.

tôi đã cố gắng để tìm một cách để thêm các đơn vị xét nghiệm để áp dụng nhưng cuối cùng chỉ bị mắc kẹt trong một catch-22:

  1. Để viết có nghĩa là đơn vị đầy đủ các xét nghiệm mã sẽ cần phải được tái cấu trúc.
  2. Không có kiểm tra đơn vị, sẽ quá nguy hiểm để cấu trúc lại mã.

Nếu bạn cảm thấy như một anh hùng và uống nước lạnh trên thử nghiệm đơn vị thì bạn vẫn có thể thử nhưng có nguy cơ thực sự là bạn kết thúc với nhiều mã kiểm tra ít giá trị hơn bây giờ cần được duy trì.

Đôi khi tốt nhất là làm việc trên mã theo cách được "thiết kế" để được làm việc.

0

Bạn chắc chắn là một tảng đá và một nơi khó khăn với mã cũ với phụ thuộc lớn. Bạn đã có một slog dài khó khăn trước để sắp xếp tất cả ra ngoài.

Từ những gì bạn nói, có vẻ như bạn đang cố gắng giữ mã nguồn còn nguyên vẹn cho mỗi mô-đun lần lượt, đặt nó vào một đoạn thử nghiệm với các phụ thuộc bên ngoài được chế giễu.Đề nghị của tôi ở đây sẽ là để có những bước dũng cảm hơn của cố gắng một số refactoring để loại bỏ (hoặc invert) các phụ thuộc, mà có lẽ là bước rất bạn đang cố gắng để tránh.

Tôi đề nghị điều này vì tôi đoán phụ thuộc sẽ giết bạn khi bạn viết kiểm tra. Bạn chắc chắn sẽ tốt hơn trong dài hạn nếu bạn có thể loại bỏ các phụ thuộc.

1

Tôi không biết điều này có hiệu quả với dự án của bạn hay không bạn có thể cố gắng tấn công sự cố từ liên kết liên kết của bản dựng của bạn.

Điều này sẽ loại bỏ hoàn toàn vấn đề #include của bạn. Tất cả những gì bạn cần làm là triển khai lại các giao diện trong các tệp được bao gồm để làm những gì bạn muốn và sau đó chỉ liên kết đến các tệp đối tượng giả mà bạn đã tạo để triển khai các giao diện trong tệp bao gồm.

Điểm bất lợi lớn đối với phương pháp này là hệ thống xây dựng được tuân thủ nhiều hơn.

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