आप NUnit के साथ निजी तरीकों का परीक्षण कैसे करते हैं?


104

मैं सोच रहा हूं कि NUnit का सही उपयोग कैसे किया जाए। सबसे पहले, मैंने एक अलग परीक्षण परियोजना बनाई जो संदर्भ के रूप में मेरी मुख्य परियोजना का उपयोग करती है। लेकिन उस मामले में, मैं निजी तरीकों का परीक्षण करने में सक्षम नहीं हूं। मेरा अनुमान था कि मुझे अपने परीक्षण कोड को अपने मुख्य कोड में शामिल करने की आवश्यकता है ?! - ऐसा करने का यह सही तरीका नहीं है। (मैं इसमें परीक्षण के साथ शिपिंग कोड के विचार को नापसंद करता हूं।)

आप NUnit के साथ निजी तरीकों का परीक्षण कैसे करते हैं?

जवाबों:


74

आमतौर पर, यूनिट परीक्षण एक वर्ग के सार्वजनिक इंटरफ़ेस को संबोधित करता है, इस सिद्धांत पर कि कार्यान्वयन सारहीन है, इसलिए जब तक कि परिणाम ग्राहक के दृष्टिकोण से सही न हों।

इसलिए, NUnit गैर-सार्वजनिक सदस्यों के परीक्षण के लिए कोई तंत्र प्रदान नहीं करता है।


1
+1 मैं अभी इस मुद्दे के खिलाफ आया हूं और मेरे मामले में एक "मैपिंग" एल्गोरिथम है जो निजी और सार्वजनिक अर्थों के बीच होता है अगर मैं यूनिट टेस्ट जनता के लिए होता था, तो यह वास्तव में एक एकीकरण परीक्षण होगा। इस परिदृश्य में, मुझे लगता है कि यह कोड में एक डिजाइन समस्या के लिए परीक्षण बिंदुओं को लिखने की कोशिश कर रहा है। जिस स्थिति में मुझे शायद एक अलग वर्ग बनाना चाहिए जो उस "निजी" विधि को करता है।
एंडी

140
मैं इस तर्क से पूरी तरह असहमत हूं। इकाई परीक्षण कक्षा के बारे में नहीं है, यह कोड के बारे में है । यदि मेरे पास एक सार्वजनिक विधि के साथ एक वर्ग है, और दस निजी लोगों ने सार्वजनिक एक का परिणाम बनाने के लिए उपयोग किया है, तो मेरे पास प्रत्येक निजी विधि को सुनिश्चित तरीके से काम करने का कोई तरीका नहीं है। मैं सार्वजनिक विधि पर परीक्षण के मामले बनाने की कोशिश कर सकता था जो सही तरीके से सही निजी पद्धति से टकराता था। लेकिन मुझे तब कोई पता नहीं था कि क्या वास्तव में निजी पद्धति को बुलाया गया था, जब तक कि मैं सार्वजनिक पद्धति पर भरोसा नहीं करता कि कभी भी परिवर्तन न हो। निजी तरीकों से कोड के उत्पादन उपयोगकर्ताओं के लिए निजी होने का इरादा है, लेखक नहीं।
क्वांगो

3
@ क्यूंगो, एक मानक परीक्षण सेटअप में, "लेखक" कोड का एक उत्पादन उपयोगकर्ता है। फिर भी, यदि आप एक डिज़ाइन समस्या को सूँघते नहीं हैं, तो आपके पास वर्ग में बदलाव किए बिना गैर-सार्वजनिक तरीकों के परीक्षण के लिए विकल्प हैं। System.Reflectionआपको गैर-सार्वजनिक विधियों को बाध्यकारी झंडे का उपयोग करने और उपयोग करने की अनुमति देता है, जिससे आप NUnit को हैक कर सकते हैं या अपना स्वयं का ढांचा स्थापित कर सकते हैं। या (आसान, मुझे लगता है), आप एक्सेस मॉडिफायर को बदलने के लिए एक कंपाइल-टाइम फ्लैग (#if TESTING) सेट कर सकते हैं, जिससे आप मौजूदा फ्रेमवर्क का उपयोग कर सकते हैं।
हार्पो

23
एक निजी पद्धति एक कार्यान्वयन विवरण है। इकाई परीक्षण होने का एक बहुत बिंदु व्यवहार में बदलाव के बिना कार्यान्वयन को फिर से शुरू करने की अनुमति देना है । यदि निजी तरीके इतने जटिल हो जाते हैं कि कोई उन्हें व्यक्तिगत रूप से परीक्षणों के साथ कवर करना चाहेगा, तो इस लेम्मा का उपयोग किया जा सकता है: "एक निजी पद्धति हमेशा एक अलग वर्ग की एक सार्वजनिक (या आंतरिक) विधि हो सकती है"। यही है, अगर तर्क का एक टुकड़ा परीक्षण के अधीन होने के लिए पर्याप्त रूप से उन्नत है, तो यह संभवतः अपने स्वयं के परीक्षणों के साथ अपने स्वयं के वर्ग होने के लिए उम्मीदवार है।
एंडर्स फोर्सग्रेन

6
@AndersForsgren लेकिन एकीकरण या कार्यात्मक परीक्षण के विपरीत इकाई परीक्षण की बात , इस तरह के विवरण का परीक्षण करने के लिए ठीक है। और कोड-कवरेज को एक महत्वपूर्ण इकाई-परीक्षण मीट्रिक माना जाता है, इसलिए सिद्धांत रूप में तर्क का हर टुकड़ा "परीक्षण के अधीन होने के लिए पर्याप्त रूप से उन्नत है"।
काइल स्ट्रैंड

57

जबकि मैं मानता हूं कि यूनिट टेस्टिंग का फोकस पब्लिक इंटरफेस होना चाहिए, अगर आप निजी तरीकों का भी परीक्षण करते हैं तो आपको अपने कोड का अधिक दानेदार आभास मिलता है। MS परीक्षण रूपरेखा PrivateObject और PrivateType के उपयोग के माध्यम से इसके लिए अनुमति देता है, NUnit नहीं करता है। इसके बजाय मैं क्या कर रहा हूँ:

private MethodInfo GetMethod(string methodName)
{
    if (string.IsNullOrWhiteSpace(methodName))
        Assert.Fail("methodName cannot be null or whitespace");

    var method = this.objectUnderTest.GetType()
        .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);

    if (method == null)
        Assert.Fail(string.Format("{0} method not found", methodName));

    return method;
}

इस तरह से इसका मतलब है कि आपको टेस्टेबिलिटी के पक्ष में एनकैप्सुलेशन से समझौता नहीं करना है। यदि आप निजी स्थैतिक विधियों का परीक्षण करना चाहते हैं, तो आपको अपने BindingFlags को संशोधित करने की आवश्यकता होगी। उपरोक्त उदाहरण सिर्फ उदाहरण के तरीकों के लिए है।


7
उन छोटे सहायक तरीकों का परीक्षण इकाई परीक्षण में इकाई भाग को पकड़ता है। सभी उपयोगिता वर्गों के लिए उपयुक्त नहीं हैं।
जोहान लार्सन

12
मुझे ठीक इसी की आवश्यकता थी। धन्यवाद! मुझे बस यह जांचना था कि एक निजी क्षेत्र ठीक से सेट हो रहा है, और मुझे यह जानने के लिए 3 घंटे खर्च करने की आवश्यकता है कि सार्वजनिक इंटरफ़ेस के माध्यम से यह कैसे निर्धारित किया जाए। यह मौजूदा कोड है जिसे एक बार फिर से नहीं देखा जा सकता है। यह हास्यास्पद है कि आदर्शवादी हठधर्मिता के साथ एक सरल प्रश्न का उत्तर कैसे दिया जा सकता है ...
दरोगा

5
यह चयनित उत्तर होना चाहिए, क्योंकि यह एकमात्र ऐसा है जो वास्तव में प्रश्न का उत्तर देता है।
बावज़ा

6
माना। चुने गए उत्तर की अपनी खूबियां हैं, लेकिन "क्या मुझे निजी तरीकों का परीक्षण करना चाहिए" का जवाब ओपी का सवाल नहीं है।
चेस्टरबेर

2
यह काम करता है। धन्यवाद! यह वही है जो बहुत से लोग खोज रहे हैं। यह चयनित उत्तर होना चाहिए,
सक्षम जॉनसन

47

यूनिट टेस्ट लिखने के लिए एक सामान्य पैटर्न केवल सार्वजनिक तरीकों का परीक्षण करना है।

यदि आप पाते हैं कि आपके पास कई निजी विधियां हैं, जिन्हें आप परीक्षण करना चाहते हैं, तो सामान्य रूप से यह एक संकेत है कि आपको अपने कोड को फिर से भरना चाहिए।

इन तरीकों को उस वर्ग पर सार्वजनिक करना गलत होगा जहां वे वर्तमान में रहते हैं। यह उस अनुबंध को तोड़ देगा जो आप चाहते हैं कि वह वर्ग है।

हो सकता है कि उन्हें एक सहायक वर्ग में ले जाना और उन्हें वहां सार्वजनिक करना सही हो। हो सकता है कि यह वर्ग आपके एपीआई से उजागर न हो।

इस तरह से परीक्षण कोड आपके सार्वजनिक कोड के साथ कभी नहीं मिलाया जाता है।

इसी तरह की समस्या निजी कक्षाओं का परीक्षण कर रही है। कक्षाएं जो आप अपने विधानसभा से निर्यात नहीं करते हैं। इस स्थिति में आप स्पष्ट रूप से अपने परीक्षण कोड असेंबली को प्रोडक्शन कोड असेंबली का एक दोस्त बना सकते हैं, जो कि इंटरटेन्शलवेन्विटेक्टो का उपयोग कर रहा है।


1
+ 1 हाँ! मैं सिर्फ अपने परीक्षण, अच्छी सलाह लिखते समय उस निष्कर्ष पर आया हूं!
एंडी

1
निजी तरीकों को स्थानांतरित करना जो आप परीक्षण करना चाहते हैं, लेकिन एपीआई के उपयोगकर्ताओं को एक अलग वर्ग से उजागर नहीं करते हैं जो उजागर नहीं होते हैं और उन्हें सार्वजनिक करते हैं, ठीक वही है जो मैं देख रहा था।
थॉमस एन

धन्यवाद @ मोरिचिल्ली इससे पहले कभी भी इंटरनैशनलविजिटो को नहीं देखा था। परीक्षण बहुत आसान बना दिया।
एंड्रयू मैकनॉटन

नमस्ते। हाल ही में कोई टिप्पणी नहीं के साथ कुछ नीचे वोट मिले। कृपया अपने विचारों या चिंताओं को समझाने के लिए कुछ प्रतिक्रिया दें।
मोरचिल्ली

6
इसलिए यदि आपके पास एक निजी तरीका है जिसे एक वर्ग के भीतर कई स्थानों पर बुलाया जा रहा है, तो केवल उस वर्ग द्वारा आवश्यक कुछ विशिष्ट करने के लिए और इसे सार्वजनिक एपीआई के हिस्से के रूप में उजागर नहीं किया जाना चाहिए ... आप कह रहे हैं कि इसे एक सहायक में रखें। सिर्फ परीक्षा देने के लिए कक्षा? आप इसे केवल कक्षा के लिए सार्वजनिक कर सकते हैं।
डेनियल मैकियास

21

अपने परीक्षण असेंबली को आपके द्वारा परीक्षण की जा रही असेंबली के मित्र विधानसभा के रूप में घोषित करके निजी तरीकों का परीक्षण करना संभव है। विवरण के लिए नीचे दिए गए लिंक को देखें:

http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx

यह उपयोगी हो सकता है क्योंकि यह आपके उत्पादन कोड से आपके परीक्षण कोड को अलग करता है। मैंने कभी भी इस विधि का उपयोग खुद नहीं किया है क्योंकि मुझे इसकी आवश्यकता कभी नहीं मिली है। मुझे लगता है कि आप इसका उपयोग चरम परीक्षण के मामलों की कोशिश और परीक्षण करने के लिए कर सकते हैं, जिसे आप अपने परीक्षण वातावरण में केवल यह देखने के लिए दोहरा नहीं सकते कि आपका कोड इसे कैसे संभालता है।

जैसा कि कहा गया है, हालांकि, आपको वास्तव में निजी तरीकों का परीक्षण करने की आवश्यकता नहीं है। आप लाइक से ज्यादा अपने कोड को छोटे बिल्डिंग ब्लॉक्स में रिफलेक्टर करना चाहते हैं। एक टिप जो आपको रिफ्लेक्टर में आने में मदद कर सकता है वह है उस डोमेन के बारे में सोचना और सोचना जो आपके सिस्टम से संबंधित है और इस डोमेन में रहने वाली 'वास्तविक' वस्तुओं के बारे में सोचना है। आपके सिस्टम में आपकी वस्तुओं / कक्षाओं को सीधे एक वास्तविक वस्तु से संबंधित होना चाहिए जो आपको उस सटीक व्यवहार को अलग करने की अनुमति देगा जो ऑब्जेक्ट में होना चाहिए और वस्तुओं की जिम्मेदारियों को भी सीमित करना चाहिए। इसका मतलब यह होगा कि आप किसी विशेष विधि का परीक्षण करने के लिए केवल संभव बनाने के बजाय तार्किक रूप से पुन: निर्माण कर रहे हैं; आप वस्तुओं के व्यवहार का परीक्षण करने में सक्षम होंगे।

यदि आपको अभी भी आंतरिक परीक्षण की आवश्यकता महसूस होती है, तो आप अपने परीक्षण में मॉकिंग पर भी विचार कर सकते हैं क्योंकि आप एक कोड के एक टुकड़े पर ध्यान केंद्रित करना चाहते हैं। मॉकिंग वह जगह है जहां आप एक ऑब्जेक्ट पर निर्भरता को इंजेक्ट करते हैं लेकिन इंजेक्ट की गई वस्तुएं 'वास्तविक' या उत्पादन ऑब्जेक्ट नहीं हैं। वे कठिन व्यवहार वाले डमी ऑब्जेक्ट हैं जो व्यवहार की त्रुटियों को अलग करना आसान बनाते हैं। Rhino.Mocks एक लोकप्रिय मुफ्त मॉकिंग फ्रेमवर्क है जो अनिवार्य रूप से आपके लिए ऑब्जेक्ट लिखेगा। TypeMock.NET (उपलब्ध सामुदायिक संस्करण के साथ एक वाणिज्यिक उत्पाद) एक अधिक शक्तिशाली ढांचा है जो सीएलआर वस्तुओं का मजाक उड़ा सकता है। डेटाबेस एप्लिकेशन का परीक्षण करते समय उदाहरण के लिए SqlConnection / SqlCommand और Datatable वर्गों का मजाक उड़ाने के लिए बहुत उपयोगी है।

उम्मीद है कि यह उत्तर आपको यूनिट परीक्षण के बारे में सामान्य रूप से सूचित करने और यूनिट परीक्षण से बेहतर परिणाम प्राप्त करने में आपकी मदद करने के लिए थोड़ी और जानकारी देगा।


12
आंतरिक तरीकों का परीक्षण करना संभव है , निजी नहीं (NUnit के साथ)।
ट्रूविल

6

मैं निजी तरीकों का परीक्षण करने की क्षमता रखने के पक्ष में हूं। जब कोड शुरू होने के बाद xUnit ने शुरू किया, तो इसका परीक्षण कार्यक्षमता के लिए इरादा था। इंटरफ़ेस का परीक्षण इस उद्देश्य के लिए पर्याप्त है।

इकाई परीक्षण परीक्षण संचालित विकास के लिए विकसित हुआ है। सभी तरीकों का परीक्षण करने की क्षमता होने से उस एप्लिकेशन के लिए उपयोगी है।


5

यह प्रश्न इसके उन्नत वर्षों में है, लेकिन मुझे लगा कि मैं इसे करने का अपना तरीका साझा करूंगा।

मूल रूप से, मेरे पास विधानसभा में मेरी सभी इकाई परीक्षण कक्षाएं हैं जो वे उस विधानसभा के लिए 'डिफ़ॉल्ट' के नीचे 'यूनिटटेस्ट' नामस्थान में परीक्षण कर रहे हैं - प्रत्येक परीक्षण फ़ाइल में लिपटे हैं:

#if DEBUG

...test code...

#endif

ब्लॉक, और उस सभी का मतलब है कि ए) यह एक रिलीज में वितरित नहीं किया जा रहा है और बी) मैं हूप जंपिंग के बिना internal/ Friendस्तर की घोषणाओं का उपयोग कर सकता हूं ।

दूसरी बात यह है कि इस प्रश्न के लिए अधिक प्रासंगिक, partialकक्षाओं का उपयोग है , जिसका उपयोग निजी तरीकों के परीक्षण के लिए एक प्रॉक्सी बनाने के लिए किया जा सकता है, इसलिए उदाहरण के लिए किसी निजी विधि की तरह कुछ परीक्षण करना जो पूर्णांक मान लौटाता है:

public partial class TheClassBeingTested
{
    private int TheMethodToBeTested() { return -1; }
}

विधानसभा के मुख्य वर्गों में, और परीक्षण वर्ग:

#if DEBUG

using NUnit.Framework;

public partial class TheClassBeingTested
{
    internal int NUnit_TheMethodToBeTested()
    {
        return TheMethodToBeTested();
    }
}

[TestFixture]
public class ClassTests
{
    [Test]
    public void TestMethod()
    {
        var tc = new TheClassBeingTested();
        Assert.That(tc.NUnit_TheMethodToBeTested(), Is.EqualTo(-1));
    }
}

#endif

जाहिर है, आपको यह सुनिश्चित करने की आवश्यकता है कि आप इस पद्धति का उपयोग विकास करते समय नहीं करते हैं, हालांकि एक रिलीज बिल्ड जल्द ही एक अनजाने कॉल को इंगित करेगा यदि आप करते हैं।


4

इकाई परीक्षण का मुख्य लक्ष्य एक वर्ग के सार्वजनिक तरीकों का परीक्षण करना है। वे सार्वजनिक तरीके उन निजी तरीकों का उपयोग करेंगे। इकाई परीक्षण सार्वजनिक रूप से उपलब्ध क्या है के व्यवहार का परीक्षण करेगा।


3

माफी अगर यह सवाल का जवाब नहीं देता है, लेकिन प्रतिबिंब का उपयोग, #if #endif बयान या निजी तरीकों को दृश्यमान बनाने जैसे समाधान समस्या का समाधान नहीं करते हैं। निजी तरीकों को दिखाई न देने के कई कारण हो सकते हैं ... क्या होगा यदि यह उत्पादन कोड है और उदाहरण के लिए टीम पूर्वव्यापी रूप से इकाई परीक्षण लिख रही है।

जिस परियोजना के लिए मैं केवल MSTest (दुख की बात) पर काम कर रहा हूं वह एक तरीका है, एक्सेसरों का उपयोग करके, निजी तरीकों की जांच करने के लिए।


2

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

आपको बस कुछ भी परीक्षण नहीं करना चाहिए जो सार्वजनिक नहीं है।

यदि आपके पास कुछ आंतरिक विधियां और गुण हैं, तो आपको या तो सार्वजनिक रूप से बदलने पर विचार करना चाहिए, या ऐप के साथ अपने परीक्षणों को शिप करना चाहिए (कुछ ऐसा जो मैं वास्तव में समस्या के रूप में नहीं देखता)।

यदि आपका ग्राहक टेस्ट-सूट चलाने में सक्षम है और देखें कि आपके द्वारा दिया गया कोड वास्तव में "काम" कर रहा है, तो मैं इसे एक समस्या के रूप में नहीं देखता (जब तक आप इसके माध्यम से अपना आईपी नहीं देते)। मैं हर रिलीज़ में शामिल चीजों का परीक्षण-रिपोर्ट और कोड कवरेज रिपोर्ट करता हूं।


कुछ ग्राहक बजट को छोटा रखने की कोशिश करते हैं और परीक्षणों के दायरे पर चर्चा शुरू करते हैं। इन लोगों को यह समझाना कठिन है कि परीक्षण लिखना इसलिए नहीं है क्योंकि आप एक बुरे कोडर हैं और अपने स्वयं के कौशल पर भरोसा नहीं करते हैं।
MrFox

1

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

इसलिए यदि आप वास्तव में आंतरिक सदस्यों का परीक्षण करना चाहते हैं तो आप इनमें से किसी एक दृष्टिकोण का उपयोग कर सकते हैं:

  1. अपने सदस्य को सार्वजनिक करें। कई पुस्तकों में लेखक इस दृष्टिकोण को सरल बताते हैं
  2. आप अपने सदस्यों को आंतरिक बना सकते हैं और आंतरिक अदृश्य को जोड़ सकते हैं Assebly में से जोड़ा जा सकता है
  3. आप कक्षा के सदस्यों को अपने परीक्षण वर्ग से अपने परीक्षण वर्ग को संरक्षित और विरासत में दे सकते हैं।

कोड उदाहरण (छद्म कोड):

public class SomeClass
{
    protected int SomeMethod() {}
}
[TestFixture]
public class TestClass : SomeClass{

    protected void SomeMethod2() {}
    [Test]
    public void SomeMethodTest() { SomeMethod2(); }
}

ऐसा लगता है कि कॉकरोच आपके उदाहरण कोड के अंदर छिपा हुआ है;) NUnit की स्थिरता के अंदर विधि सार्वजनिक होनी चाहिए, अन्यथा आप प्राप्त करते हैं Message: Method is not public
Gucu112

@ Gucu112 धन्यवाद। मैंने ठीक कर दिया। सामान्य तौर पर यह मायने नहीं रखता क्योंकि लक्ष्य को डिज़ाइन पोव से aproach दिखाना है।
बुर्जुग

1

आप अपने तरीकों को आंतरिक संरक्षित कर सकते हैं, और फिर assembly: InternalsVisibleTo("NAMESPACE") अपने परीक्षण नामस्थान का उपयोग कर सकते हैं।

इसलिए, नहीं! आप निजी तरीकों तक नहीं पहुंच सकते, लेकिन यह एक काम है।


0

मैं निजी तरीकों के पैकेज को स्पष्ट करूंगा। इस तरह आप उन तरीकों का परीक्षण करने में सक्षम होने के बावजूद इसे यथोचित रूप से निजी रखते हैं। मैं लोगों से यह कहते हुए सहमत नहीं हूं कि सार्वजनिक इंटरफेस केवल वही हैं जिनका परीक्षण किया जाना चाहिए। निजी तरीकों में अक्सर महत्वपूर्ण कोड होता है जिसे केवल बाहरी इंटरफेस के माध्यम से ठीक से परीक्षण नहीं किया जा सकता है।

यदि आप सही कोड या जानकारी छिपाने के बारे में अधिक परवाह करते हैं तो यह वास्तव में उबलता है। मैं कहता हूं कि पैकेज विजिबिलिटी एक अच्छा समझौता है क्योंकि उन तरीकों को एक्सेस करने के लिए किसी को आपके पैकेज में अपनी क्लास लगानी होगी। यह वास्तव में उन्हें दो बार सोचना चाहिए कि क्या यह वास्तव में स्मार्ट चीज है।

मैं एक जावा पुरुष btw हूँ, इसलिए पैकेज visiblilty को C # में पूरी तरह से अलग कहा जा सकता है। यह कहने के लिए पर्याप्त है कि यह दो वर्गों को उन तरीकों तक पहुँचने के लिए एक ही नामस्थान में होना है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.