2013-04-09 6 views
8

जब मैं एक इंटरफ़ेस लिख रहा हूं, तो इंटरफ़ेस के समान पैकेज में अपने परीक्षणों को परिभाषित करना अक्सर सुविधाजनक होता है, और फिर इंटरफ़ेस सेट को लागू करने वाले कई पैकेजों को परिभाषित करता है, उदाहरण के लिए।मेरे पास एकाधिक पैकेजों के लिए एक सामान्य परीक्षण सूट कैसे हो सकता है?

package/ 
package/impl/x <-- Implementation X 
package/impl/y <-- Implementation Y 

वहाँ एक आसान तरीका एक ही टेस्ट स्वीट (इस मामले में, पैकेज/* _ test.go में स्थित) उप संकुल में चलाने के लिए है?

सबसे अच्छा समाधान मैं अब तक लेकर आए हैं एक परीक्षण पैकेज को जोड़ने के लिए है:

package/tests/ 

कौन सा टेस्ट स्वीट लागू करता है, और कार्यान्वयन में से प्रत्येक में एक परीक्षण परीक्षण चलाने के लिए, लेकिन यह दो कमियां हैं:

1) पैकेज में परीक्षण/परीक्षण _test.go फ़ाइलें में नहीं हैं, और वास्तविक पुस्तकालय, godoc द्वारा प्रलेखित का हिस्सा होने अंत, आदि

2) पैकेज में परीक्षण/परीक्षण एक कस्टम टेस्ट धावक द्वारा चलाए जाते हैं, जिन्हें मूल रूप से सभी को डुप्लिकेट करना होता है परीक्षणों के लिए स्कैन करने और उन्हें चलाने के लिए 'जाने के परीक्षण' की कार्यक्षमता।

एक सुंदर कठोर समाधान की तरह लगता है।

क्या ऐसा करने का एक बेहतर तरीका है?

उत्तर

7

मैं एक अलग परीक्षण पुस्तकालय का उपयोग करने के विचार को वास्तव में नापसंद नहीं करता हूं। यदि आपके पास इंटरफ़ेस है और आपके पास प्रत्येक इंटरफ़ेस के लिए सामान्य परीक्षण हैं, तो अन्य इंटरफ़ेस को लागू करने वाले अन्य लोग इन परीक्षणों का भी उपयोग करना पसंद कर सकते हैं।

आप एक पैकेज "package/test" एक समारोह में शामिल है कि

// functions needed for each implementation to test it 
type Tester struct { 
    func New() package.Interface 
    func (*package.Interface) Done() 
    // whatever you need. Leave nil if function does not apply 
} 

func TestInterface(t *testing.T, tester Tester) 

सूचना है कि TestInterface के हस्ताक्षर क्या go test उम्मीद करने के लिए मेल नहीं खाता बना सकते हैं। अब, प्रत्येक पैकेज के लिए package/impl/x आप एक फाइल generic_test.go जोड़ें:

package x 

import "testing" 
import "package/test" 

// run generic tests on this particular implementation 
func TestInterface(t *testing.T) { 
    test.TestInterface(t,test.Tester{New:New}) 
} 

कहाँ New() अपने कार्यान्वयन के निर्माता कार्य है। इस योजना के साथ लाभ यह है कि

  1. आपका परीक्षण, जो कोई भी अपने इंटरफेस को लागू करता है के लिए पुन: प्रयोज्य हैं अन्य संकुल
  2. यह तुरंत स्पष्ट है कि आप जेनेरिक टेस्ट स्वीट चलाने
  3. परीक्षण मामलों में जहां से भी है कार्यान्वयन न कि किसी अन्य पर है, अस्पष्ट जगह
  4. कोड आसानी से अनुकूलित किया जा सकता एक कार्यान्वयन विशेष प्रारंभ या इसी तरह के सामान
  5. यह go test संगत है की जरूरत है (बड़ा प्लस!)

बेशक, कुछ मामलों में आपको अधिक जटिल TestInterface फ़ंक्शन की आवश्यकता है, लेकिन यह मूलभूत विचार है।

+0

हाँ, यह बहुत कुछ है जो मैं कर रहा हूं (विभिन्न तर्कों का उपयोग करके इम्प्लायर को सेटअप और टियरडाउन फ़ंक्शन को अगर चाहें तो आपूर्ति करने दें); जैसा कि मैंने कहा था, यद्यपि जेनरेटेड डॉक आउटपुट में फ़ंक्शन चालू होने के लिए थोड़ा परेशान है, और एक 'मेगा टेस्ट' है जो सभी उप परीक्षणों को चलाता है, उस आइटम पर उम्र के लिए 'परीक्षण करें' लटकता है (मैं इसके साथ सहमत हूं आपके सभी अन्य बिंदुएं)। – Doug

+0

@Doug मैं सहायक कार्यों और डेटा के लिए एक संरचना का उपयोग करना पसंद करते हैं; यह बहुत साफ है और यदि ऐसा कोई फ़ंक्शन नहीं है तो आप शून्य (पॉइंटर्स के लिए डिफ़ॉल्ट मान) की आपूर्ति कर सकते हैं। इसके अलावा, यदि आप [test.Short()] (http://golang.org/pkg/testing/#Short) सेट करते हैं और कुछ परीक्षण मामलों को तोड़ते हैं तो आप कुछ परीक्षणों को पट्टी करना चाहेंगे। – fuz

+0

@ डौग बीटीडब्ल्यू, क्या बात यह है कि परीक्षण कार्यों में प्रलेखन में दिखाया गया है? यदि आप दस्तावेज़ीकरण को अव्यवस्थित करते हैं तो आप उन्हें दूसरे पैकेज में ले जा सकते हैं (जैसा कि मैंने सुझाव दिया)। – fuz

1

यदि आप विभिन्न संकुलों द्वारा पुन: उपयोग के लिए कोड का एक टुकड़ा साझा करते हैं तो हाँ, यह परिभाषा के अनुसार एक पुस्तकालय है। यहां तक ​​कि जब * _test.go फ़ाइलों से परीक्षण के लिए उपयोग किया जाता है। यह _test.go फ़ाइल में "fmt" के "परीक्षण" को आयात करने से अलग नहीं है। और गॉडोक द्वारा प्रलेखित एपीआई एक प्लस है, आईएमएचओ से कम नहीं है।

1

शायद कुछ यहां थोड़ा मिश्रित हो जाता है: यदि पैकेज में कोई अंतर नहीं है तो पर कोई कोड नहीं है क्योंकि गो में इंटरफ़ेस कार्यान्वयन मुक्त हैं।

तो मुझे लगता है कि पैकेज में आपके इंटरफ़ेस में बाधाएं हैं। जैसे

interface Walker { 
    Walk(step int) 
    Tired() bool 
} 
में

आप अनुबंध मानता है कि थक रिटर्न सच यदि एक से अधिक 500 चरणों Walk'ed (और झूठे अन्यथा) किया गया है और अपने परीक्षण कोड इन निर्भरताओं (या धारणा, अनुबंध, अपरिवर्तनशीलताओं जो कुछ भी आप की जाँच करता है नाम दें)।

यदि यह स्थिति मैं प्रदान करेगा (पैकेज एक में) एक निर्यात समारोह

func TestWalkerContract(w Walker) error { 
    w.Walk(100) 
    if w.Tired() { return errors.New("Tired after 100 steps") } 
    w.Walk(450) 
    if !w.Tired() { return errors.New("Not tired after 100+450 steps") } 
} 

कौन सा ठीक से अनुबंध दस्तावेजों और प्रकार को लागू करने का परीक्षण करने के वॉकर के साथ संकुल द्वारा इस्तेमाल किया जा सकता बी और सी है उनके b_test.go और c_test.go में कार्यान्वयन । आईएमएचओ यह बिल्कुल ठीक है कि इन टेस्टवाल्कर कंट्रैक्ट जैसे फ़ंक्शन गॉडोक द्वारा प्रदर्शित किए जाते हैं।

पीएस चलने और थकने से अधिक आम एक त्रुटि स्थिति हो सकती है जिसे साफ़/रीसेट किए जाने तक रखा और रिपोर्ट किया जाता है।

संबंधित मुद्दे

 संबंधित मुद्दे