2009-06-19 41 views
6

Tôi đang thiết lập một loạt các bài kiểm tra đơn vị sử dụng CppUnit nhưng có vấn đề là không có bài kiểm tra nào đang được chạy. Dự án được chia thành nhiều thư viện nhỏ và tôi đã lên kế hoạch chia các lớp thử nghiệm đơn vị theo cùng một cách và sau đó liên kết tất cả chúng thành một chương trình thử nghiệm duy nhất. Vấn đề là, sau đó các lớp kiểm tra được trong các thư viện riêng của họ, họ không được liên kết vào chương trình thử nghiệm chính, trừ khi tôi dứt khoát gọi cho họ, tức là tôi phải đưa vàoLiên kết trong các thư viện thử nghiệm với CppUnit

runner.addTest(TestClass::suite());

riêng cho mỗi bài kiểm tra và không thể sử dụng phương thức makeTests() của TestFactoryRegistry để lấy danh sách các bài kiểm tra. Nếu tôi chỉ biên dịch tất cả chúng lại với nhau trong thư mục trên, phương thức makeTests() hoạt động tốt nhưng tôi không muốn có tất cả các lớp thử nghiệm ở một vị trí nếu tôi có thể giúp nó.

Các tài liệu CppUnit đưa ra gợi ý nhỏ sau đây

Linking vấn đề khi sử dụng Helper macro?

Khi bạn tạo một dự án và viết dãy đơn vị thử nghiệm của mình, công việc được thực hiện dễ dàng hơn thông qua việc sử dụng các cái gọi là macro helper: CPPUNIT_TEST_SUITE_NAMED_REGISTRATION, CPPUNIT_REGISTRY_ADD và CPPUNIT_REGISTRY_ADD_TO_DEFAULT. Vấn đề là nếu bạn sử dụng những macro trong file mã nguồn của một lớp TestFixture (nói MyTest làm ví dụ ), và nếu bạn sử dụng một dòng như này một

runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest() 

);

trong hàm main() của bạn trong tệp main.cpp, sẽ không chạy thử nghiệm nào cả!

Lý do đơn giản là các giai đoạn liên kết , một trong những bước của quá trình xây dựng , không chèn các đối tượng file (.obj hoặc file .o) trong trận chung kết thực thi nếu không có xác định biểu tượng trong main.cpp của bạn.

Bằng cách đó, mã đối tượng mà chứa AutoRegister tĩnh biến instantiation không phải là một phần của thực thi cuối cùng và không thể để chèn mình vào runner trong chính) chức năng (.

Bạn phải tạo một biểu tượng không xác định trong main.cpp sao cho tệp mytest.o được tích hợp với main.o vào thực thi cuối cùng.

Lừa cam kết bởi Michel Nolard

nhưng không nói làm thế nào để làm cho công việc này và tôi là vừa đủ dày đặc không để có thể hình dung nó ra bản thân mình hoặc tìm một ví dụ trực tuyến.

Bây giờ tôi có thể thực hiện một bài kiểm tra thực thi riêng biệt cho mỗi thư viện, và cuối cùng tôi có thể đi theo cách đó, nhưng tôi muốn cố gắng làm việc này trước tiên nên tôi chỉ có một chương trình thử nghiệm để chạy thử tất cả mọi thứ. Bất kỳ ý tưởng/ví dụ về làm thế nào để có được điều này để làm việc?

Trả lời

1

Bằng cách thêm biểu tượng không xác định vào chính, anh ấy chỉ có nghĩa là tạo bất kỳ biểu tượng bên ngoài ngẫu nhiên nào để buộc trình liên kết tìm kiếm các thư viện bên ngoài của bạn chứa mã kiểm tra.

Ví dụ, giả sử hai thư viện kiểm tra Fred và Barney, trong fredTestLib.cpp bạn chỉ muốn thêm dòng này:

int fredDummyInt = 0; // declare a unique symbol for the linker to resolve 

và trong barneyTestLib.cpp, bạn muốn thêm một dòng tương tự:

int barneyDummyInt = 0; // a different unique symbol for the linker to resolve 

Bạn có thể biên dịch từng thư viện riêng biệt theo các bước khác nhau. Trong chương trình thử nghiệm chính, sau đó bạn buộc trình liên kết giải quyết chúng. Vì vậy, thêm những dòng này vào main.cpp:

extern int fredDummyInt; 
extern int barneyDummyInt; 
... 
main() { 
    ... 
    fredDummyInt++; // give the linker some symbols to resolve 
    barneyDummyInt++; 
    ... 

Ý tưởng (theo những gì tác giả của trick ở trên đang nói) là vì các mối liên kết đã được tìm kiếm fredTest.lib cho fredDummyInt, nó cũng sẽ tìm và giải quyết các bài kiểm tra được đăng ký tự động của bạn.

Lưu ý: Tôi chưa thử cách này để xem nó có hoạt động không! Tôi chỉ trả lời câu hỏi của bạn về những người bên ngoài.

Một cách tiếp cận khác để xem xét là tạo các thử nghiệm của bạn trong các tệp DLL và sử dụng LoadLibrary() để đưa chúng vào chạy một cách rõ ràng. Đối với quá mức cần thiết, nếu bạn sử dụng MfcUi :: TestRunner, bạn có thể xây dựng một giao diện thả xuống nhỏ cho phép bạn chọn thư viện để tải, tải nó, sau đó hiển thị các kiểm tra để chạy trong thư viện đó, sau đó chạy chúng.

+0

Tôi sẽ dùng thử tối nay. – dagorym

+0

Nó gần như làm việc như thế nào tôi muốn nó. Thêm điều này vào làm cho hệ thống đăng ký nhận các thử nghiệm trong tệp chứa biến bên ngoài nhưng không phải từ tất cả các kiểm tra trong thư viện. Có khoảng một chục lớp (mỗi tệp riêng của họ) trong thư viện và nó chỉ chọn các bài kiểm tra cho một biến. Đây thực sự là hành vi đúng nhưng không mua cho tôi bất cứ thứ gì hơn bao gồm từng lớp riêng lẻ. Tôi đã rất hy vọng điều này sẽ làm việc. – dagorym

+0

Vâng, bạn đang cố gắng để có được "ma thuật" kết quả mà không có mã, và trong khi tôi khen bạn về nỗ lực của bạn, tại một số điểm tất cả chúng ta phải viết mã để có được công việc làm. Tôi hoàn toàn đồng ý rằng tự duy trì mã là loại tốt nhất (những thứ mà nó "chỉ hoạt động") nhưng bạn đang tìm kiếm để vượt ra ngoài ranh giới của một mô-đun duy nhất ở đây, và đó là nơi nó có để có được khôn lanh. Người liên kết nên biết khi nào nên ngừng đưa thư viện mới? Nó có nên tìm kiếm toàn bộ ổ cứng của bạn không? Thư mục hiện tại? Thư mục con? Thư mục đường dẫn? Phải có giới hạn hợp lý, và vượt ra ngoài những giới hạn mà bạn phải cụ thể. –

0

Giải pháp cho vấn đề này khá đơn giản như statet trước đây (nhưng có thể không rất thanh lịch). Đối với mỗi TestFixture mà nằm trong một thư viện bên ngoài bạn cần phải thêm hai dòng mã sau đây trong module chính

#include <CppUnitTestFixtureExample.h> 
CppUnitTestFixtureExample Test1; 

Nó tạo ra một biến giả không sử dụng mà không được sử dụng, nó chỉ buộc các mối liên kết để liên kết thử nghiệm. Bây giờ các Á hậu thử nghiệm nằm trong mô-đun chính có thể chạy thử nghiệm.

0

Tôi nhận thấy bài đăng này hiện đã cũ nhưng đối với bất kỳ ai khác gặp phải: Một cách để giải quyết vấn đề này là hướng dẫn (buộc) trình liên kết bao gồm toàn bộ thư viện tĩnh trong nhị phân. khu vực chi tiết có sẵn từ gcc & trang ld người đàn ông, và sau này bao gồm nó quá: How to force gcc to link unreferenced, static C++ objects from a library

mỗi người đàn ông trang ld của, điều quan trọng là phải xem xét một cách rõ ràng biến tùy chọn tắt (còn được thể hiện trong một trong những ví dụ trên).

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