दृश्य स्थापित एक से बटोरता है कि पुस्तकालय जिसका gtest
परीक्षण का मामला चला जाता लापता स्थिर आवेदन के निर्माण में जुड़ा हुआ है। इसके अलावा जीएनयू टूलचेन उपयोग में है।
समस्या व्यवहार का कारण सीधा है। परीक्षण प्रोग्राम में लाइब्रेरी में किसी भी चीज़ का कोई संदर्भ नहीं है जिसमें TEST(X, just_a_passing_test)
शामिल है। तो प्रोग्रामर को लिंक करने के लिए उस लाइब्रेरी से ऑब्जेक्ट फ़ाइल को जोड़ने के लिए लिंकर की आवश्यकता नहीं है। तो यह नहीं करता है। तो gtest
रनटाइम निष्पादन योग्य में उस परीक्षण को नहीं ढूंढता है, क्योंकि यह वहां नहीं है।
यह समझने में सहायता करता है कि जीएनयू प्रारूप में एक स्थिर लाइब्रेरी एक ऑब्जेक्ट फाइलों का संग्रह है, जो घर-रखरखाव हेडर ब्लॉक और वैश्विक प्रतीक तालिका से सजा है।
ओपी पता चला कि कार्यक्रम में समस्या पुस्तकालय में किसी भी सार्वजनिक प्रतीक के लिए एक तदर्थ संदर्भ कोडिंग से, वह "जादुई" अपने परीक्षण का मामला कार्यक्रम में दबाव डाल सकता है।
कोई जादू नहीं। उस सार्वजनिक प्रतीक के संदर्भ को पूरा करने के लिए, लिंकर अब लाइब्रेरी से ऑब्जेक्ट फ़ाइल को लिंक करने के लिए बाध्य है - जिसमें प्रतीक की परिभाषा शामिल है। और ओपी प्रदान करता है कि .cpp
से पुस्तकालय बनाया गया है। तो लाइब्रेरी में केवल एक ऑब्जेक्ट फ़ाइल है, और यह में टेस्ट केस की परिभाषा भी है। उस ऑब्जेक्ट फ़ाइल के साथ लिंकेज में, परीक्षण केस प्रोग्राम में है।
ओपी एक ही अंत प्राप्त करने के लिए एक और सम्मानजनक तरीके की खोज में जीसीसी से क्लैंग, पर स्विचिंग, कंपाइलर विकल्पों के साथ व्यर्थ में twiddled। कंपाइलर अप्रासंगिक है। जीसीसी या क्लैंग, यह सिस्टम लिंकर, ld
द्वारा इसकी लिंकिंग प्राप्त करता है (जब तक इसे बदलने के लिए असामान्य उपाय नहीं किए जाते हैं)।
वहाँ ld
उस वस्तु फ़ाइल में कोई प्रतीकों को भी जब कार्यक्रम संदर्भित करता है एक स्थिर पुस्तकालय से एक वस्तु फ़ाइल से जोड़ने के लिए प्राप्त करने के लिए एक और अधिक सम्मानजनक रास्ता नहीं है?
वहाँ है। कहो समस्या कार्यक्रम app
है और समस्या को स्थिर पुस्तकालय libcool.a
फिर हमेशा की तरह जीसीसी कमांडलाइन कि app
लिंक प्रासंगिक अंक में इस जैसा दिखता है, यह है: ld
को
g++ -o app -L/path/to/the/libcool/archive -lcool
यह प्रतिनिधियों कमांडलाइन साथ, अतिरिक्त लिंकर विकल्प और लाइब्रेरीज़ g++
सिस्टम के लिए डिफ़ॉल्ट होने लगता है जहां यह स्वयं पाता है।
जब लिंकर -lcool
पर विचार करने के लिए आता है, तो यह पता लगाएगा कि यह /path/to/the/libcool/archive/libcool.a
संग्रह के लिए अनुरोध है। फिर यह पता लगाएगा कि इस बिंदु पर अभी भी हाथ में किसी भी अनसुलझे प्रतीक संदर्भ प्राप्त हुए हैं जिनकी परिभाषा libcool.a
में ऑब्जेक्ट फ़ाइलों में संकलित की गई है। यदि कोई है, तो यह उन ऑब्जेक्ट फ़ाइलों को app
से लिंक करेगा। यदि नहीं, तो यह libcool.a
से कुछ भी लिंक नहीं करता है और आगे बढ़ता है।
लेकिन हम जानते हैं कि libcool.a
में प्रतीक परिभाषाएं हैं कि हम लिंक चाहते हैं, भले ही app
उन्हें संदर्भित न करें। उस स्थिति में, हम ऑब्जेक्ट फ़ाइलों को libcool.a
से लिंक करने के लिए लिंकर बता सकते हैं भले ही वे संदर्भित न हों। दरअसल, हम g++
बताते हैं कि ऐसा करने के लिए, तो जैसे लिंकर बताने के लिए कर सकते हैं:
g++ -o app -L/path/to/the/libcool/archive -Wl,--whole-archive -lcool -Wl,-no-whole-archive
उन -Wl,...
विकल्पों g++
बता ...
ld
करने के लिए विकल्पों पारित करने के लिए। --whole-archive
विकल्प ld
को बाद के अभिलेखागार से सभी ऑब्जेक्ट फ़ाइलों को जोड़ने के लिए बताता है, चाहे वे संदर्भित हों या नहीं, आगे की सूचना तक। -no-whole-archive
ऐसा करने से रोकने के लिए ld
बताता है और सामान्य रूप से व्यवसाय को फिर से शुरू करता है।
ऐसा लगता है कि -Wl,-no-whole-archive
अनावश्यक है, क्योंकि यह g++
कमांडलाइन पर आखिरी बात है। लेकिन ऐसा नहीं है। याद रखें कि g++
ld
पर जाने से पहले, दृश्यों के पीछे, कमांडलाइन पर सिस्टम डिफ़ॉल्ट लाइब्रेरी जोड़ता है। आप निश्चित रूप से --whole-archive
नहीं चाहते हैं जब वे डिफ़ॉल्ट पुस्तकालय जुड़े हों। (लिंक कई परिभाषा त्रुटियों के साथ विफल हो जाएगा)।
समस्या मामले के लिए इस समाधान को लागू करें और TEST(X, just_a_passing_test)
कार्यक्रम के लिए मजबूर कर वस्तु फ़ाइल है कि है कि परीक्षण को परिभाषित करता है में कुछ नहीं-op संदर्भ बनाने के लिए की हैक बिना, निष्पादित किया जाएगा।
सामान्य स्थिति में इस समाधान के लिए एक स्पष्ट नकारात्मक पक्ष नहीं है। यदि ऐसा होता है कि से पुस्तकालय जो हम कुछ unreferenced वस्तु फ़ाइल के संबंध बाध्य करना चाहते हैं अन्य unreferenced वस्तु फ़ाइलों है कि हम वास्तव में की जरूरत नहीं है के गुच्छा होता है। --whole-archive
उन सभी को भी उनसे लिंक करता है, और वे प्रोग्राम में बस फंस गए हैं।
--whole-archive
समाधान अधिक सम्मानजनक हो सकता है कि कोई-op संदर्भ हैक, लेकिन यह सम्मानजनक नहीं है। यह भी सम्मानजनक नहीं है।
यहाँ वास्तविक समाधान सिर्फ उचित बात करना है। आप लिंकर अपने कार्यक्रम में कुछ की परिभाषा से जोड़ने के लिए चाहते हैं, तो लिंकर से एक रहस्य नहीं है कि नहीं रखते। कम से कम प्रत्येक संकलन इकाई में बात जहां इसकी परिभाषा में इस्तेमाल किया जा करने की उम्मीद घोषणा करते हैं।
class X_just_a_passing_test_Test : public ::testing::Test {
public:
X_just_a_passing_test_Test() {}
private:
virtual void TestBody();
static ::testing::TestInfo* const test_info_ __attribute__ ((unused));
X_just_a_passing_test_Test(X_just_a_passing_test_Test const &);
void operator=(X_just_a_passing_test_Test const &);
};
(प्लस test_info_
के लिए एक स्थिर प्रारंभकर्ता और:
gtest
परीक्षण मामलों के साथ उचित बात करने से समझ है कि एक gtest
मैक्रो TEST(X, just_a_passing_test)
की तरह इस मामले में एक वर्ग परिभाषा, के लिए विस्तारित शामिल TestBody()
के लिए एक परिभाषा)।
TEST_F
, TEST_P
वेरिएंट के लिए इसी तरह । नतीजतन, आप अपने कोड में इन मैक्रोज़ को केवल उसी बाधाओं और अपेक्षाओं के साथ तैनात कर सकते हैं जो कक्षा परिभाषाओं पर लागू होते हैं।
इस रोशनी में, यदि आप इसके लिए एक पुस्तकालय libcool
cool.h
में परिभाषित किया गया, cool.cpp
में लागू किया है और चाहते हैं gtest
इकाई परीक्षणों में परीक्षण कार्यक्रम tests
कि tests.cpp
में कार्यान्वित किया जाता, उचित बात है द्वारा निष्पादित की जाने: -
- एक हेडर फाइल लिखें,
cool_test.h
- उस में
#include "cool.h"
#include <gtest/gtest.h>
इसमें।
- फिर, यह
tests.cpp
में #include "cool_test.h"
में अपने libcool
परीक्षण मामलों को परिभाषित
- संकलित करें और
libcool
और libgtest
साथ लिंक tests.cpp
और यह स्पष्ट है कि आप क्यों नहीं होता क्या ओपी किया है। आप कक्षाएं कि tests.cpp
द्वारा की जरूरत है, और परिभाषित नहीं होता cool.cpp
की जरूरत नहीं, cool.cpp
और tests.cpp
में नहीं हैं।
ओपी पुस्तकालय में परीक्षण मामलों को परिभाषित करने के खिलाफ सलाह के खिलाफ था है क्योंकि:
और कैसे आप पुस्तकालयों का परीक्षण होता है, हर एक, जल्दी से बनाने के लिए एक निष्पादन योग्य होने के लिए उन्हें एक दर्द चलने के बिना ।
अंगूठे का एक नियम के रूप में मैं एक gtest
निष्पादन पुस्तकालय प्रति बनाए रखने के अभ्यास की सिफारिश करेंगे यूनिट परीक्षण किया जाना: उन्हें जल्दी से चल रहा है आम स्वचालन उपकरण इस तरह के एक make
साथ दर्द रहित है, और यह अब तक प्राप्त करने के लिए बेहतर है एक पास/से सिर्फ पुस्तकालयों का एक गुच्छा के लिए एक फैसले असफल पुस्तकालय प्रति फैसले। लेकिन आप अभी भी आपत्ति करने के लिए कुछ भी नहीं है कि ऐसा करने के लिए नहीं करना चाहते हैं:
// tests.cpp
#include "cool_test.h"
#include "cooler_test.h"
#include "coolest_test.h"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
संकलित करें और लिंक के साथ libcool
, libcooler
, libcoolest
और libgtest
विस्तृत जानकारी के लिए धन्यवाद। यह मेरा शक की पुष्टि में मदद करता है। अंत में मैं इकाई परीक्षण चलाने के लिए प्रत्येक पुस्तकालय के लिए निष्पादन योग्य लक्ष्य का इस्तेमाल किया। – NitrousUK
+50 अच्छे उदाहरण के साथ ग्रेट जवाब! –
मेरी मामले में मच-ओ प्रकार में पुनर्निधारणीय वस्तु फाइल करने के लिए स्टेटिक पुस्तकालय से Xcode परिवर्तन –