JUnit @Parameters का उपयोग करके उदाहरण के साथ पैरामीटरीकृत परीक्षण

⚡ स्मार्ट सारांश

पैरामीटराइज्ड परीक्षणों में JUnit एक ही परीक्षण विधि को अलग-अलग इनपुट मानों के साथ बार-बार चलाएँ, ताकि एक ही विधि कई परिदृश्यों को कवर कर सके। @RunWith और @Parameters एनोटेशन प्रत्येक पुनरावृति के लिए डेटा सेट प्रदान करते हैं।

  • 🔘 डेटा स्रोत: एक स्टैटिक @Parameters मेथड एरे का एक कलेक्शन लौटाता है, और प्रत्येक एरे एक टेस्ट इटरेशन बन जाता है।
  • धावक: @RunWith(Parameterized.class) डिफ़ॉल्ट ब्लॉक को बदल देता हैJUnit4ClassRunner प्रत्येक डेटा पंक्ति के लिए एक बार क्लास का पुनर्निर्माण करता है।
  • निर्माता: एक सार्वजनिक कंस्ट्रक्टर, परीक्षण विधि द्वारा निर्धारित इंस्टेंस फ़ील्ड में डेटा की एक पंक्ति संग्रहीत करता है।
  • 🧪 उदाहरण सहित: पांच इनपुट पंक्तियाँ sum() परीक्षण को संचालित करती हैं, और JUnit रिपोर्ट देखें। 5 में से 5 बार सफलतापूर्वक चला, शून्य विफलताओं के साथ।
  • JUnit 5: @ParameterizedTest के साथ @ValueSource, @CsvSource या @MethodSource का उपयोग करने से रनर और कंस्ट्रक्टर दोनों हट जाते हैं।
  • 📌 नुकसान: एक नॉन-स्टैटिक @Parameters मेथड, दो पब्लिक कंस्ट्रक्टर, या एक मिसिंग junit-jupiter-params डिपेंडेंसी रन को रोक देती है।

JUnit @RunWith और @Parameters एनोटेशन का उपयोग करके पैरामीटराइज्ड परीक्षण

पैरामीटराइज्ड टेस्ट क्या होता है? JUnit?

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

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

एक साधारण परीक्षण पर विचार करें जो विभिन्न संख्याओं का योग करता है। कोड कुछ इस तरह दिख सकता है:

JUnit परीक्षण विधि योग विधि के लिए तीन assertEquals कॉल दोहराती है

ऊपर बताए गए तरीके से बहुत अधिक दोहराव होता है। संख्याओं के प्रत्येक नए जोड़े के लिए उसी विधि के भीतर एक और असर्ट स्टेटमेंट की आवश्यकता होती है, और पहले असर्ट स्टेटमेंट की विफलता उसके बाद आने वाले सभी असर्ट स्टेटमेंट को छिपा देती है।

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

पैरामीटराइज़्ड बनाने के चरण JUnit टेस्ट

निम्नलिखित कोड पैरामीटराइज्ड टेस्ट का एक उदाहरण दिखाता है। यह Airthematic क्लास के sum() मेथड का परीक्षण करता है, जो कि पूरे सैंपल प्रोजेक्ट में प्रयुक्त वर्तनी है।

चरण 1) एक क्लास बनाएं। इस उदाहरण में, हम sum(int, int) विधि का उपयोग करके दो संख्याएँ इनपुट के रूप में लेंगे, जो दी गई संख्याओं का योगफल लौटाएगी।

एयरथीमेटिक क्लास एक पब्लिक सम मेथड घोषित करती है जो दो इंट आर्गुमेंट को जोड़ती है।

चरण 2) एक पैरामीटराइज्ड टेस्ट क्लास बनाएं।

टेस्ट क्लास हेडर को @RunWith(Parameterized.class) एनोटेशन से एनोटेट किया गया है और इसमें चार निजी फ़ील्ड हैं।

Code व्याख्या

  • Code रेखा 11: @RunWith(Parameterized.class) का उपयोग करके अपनी टेस्ट क्लास को एनोटेट करें।
  • Code रेखा 13: 'firstNumber' चर को निजी तथा प्रकार को int घोषित करना।
  • Code रेखा 14: 'secondNumber' नामक वेरिएबल को प्राइवेट और टाइप को int घोषित किया जा रहा है।
  • Code रेखा 15: 'expectedResult' नामक वेरिएबल को प्राइवेट और टाइप को int घोषित करना।
  • Code रेखा 16: 'airthematic' नामक चर को निजी और प्रकार को Airthematic घोषित करना।

@साथ चलाएं(क्लास_नाम.क्लास): @साथ चलाएं एनोटेशन का उपयोग रनर क्लास का नाम निर्दिष्ट करने के लिए किया जाता है। यदि हम पैरामीटर के रूप में कोई प्रकार निर्दिष्ट नहीं करते हैं, तो रनटाइम स्वयं ही चयन करेगा। खंडJUnit4क्लासरनर डिफ़ॉल्ट रूप से

यह क्लास नए टेस्ट इंस्टेंस के साथ टेस्ट चलाने के लिए ज़िम्मेदार है। यह इनवोक करने के लिए ज़िम्मेदार है। JUnit लाइफसाइकिल विधियाँ जैसे सेटअप (संसाधनों को संबद्ध करना) और टियरडाउन (संसाधनों को मुक्त करना), जिनका वर्णन इसमें किया गया है JUnit परीक्षण स्थिरता ट्यूटोरियल।

पैरामीटराइजेशन के लिए, आपको @RunWith का उपयोग करके क्लास को एनोटेट करना होगा और परीक्षण के लिए आवश्यक .class फ़ाइल पास करनी होगी।

चरण 3) एक कंस्ट्रक्टर बनाएं जो टेस्ट डेटा को स्टोर करे। इसमें 3 वेरिएबल स्टोर होंगे।

पैरामीटराइज्ड टेस्ट कंस्ट्रक्टर जो इंस्टेंस फ़ील्ड्स को तीन इंट आर्गुमेंट्स असाइन करता है

चरण 4) एक स्थैतिक विधि बनाएं जो परीक्षण डेटा उत्पन्न करे और लौटाए।

@Parameterized.Parameters एनोटेशन से युक्त स्टैटिक इनपुट विधि, जो दो-आयामी ऑब्जेक्ट ऐरे लौटाती है।

Code रेखा 32,33: दो-आयामी ऐरे बनाना (जोड़ने के लिए इनपुट पैरामीटर प्रदान करना)। asList विधि का उपयोग करके हम डेटा को List प्रकार में परिवर्तित करते हैं, क्योंकि इनपुट विधि का रिटर्न प्रकार Collection है।

Code रेखा 30: ऊपर दिए @पैरामीटर हमारे परीक्षण को चलाने के लिए इनपुट डेटा का एक सेट बनाने के लिए एनोटेशन।

@Parameters एनोटेशन द्वारा पहचाना गया स्थैतिक तरीका एक कलेक्शन लौटाता है, जिसमें प्रत्येक प्रविष्टि परीक्षण के एक पुनरावृति के लिए इनपुट डेटा होगी। तत्व {1,2,3} पर विचार करें। यहाँ:

  • पहला नंबर = 1
  • दूसरा नंबर = 2
  • अपेक्षित परिणाम = 3

यहां, क्लास को कई बार इंस्टैंशिएट किए जाने के कारण, प्रत्येक एरे एलिमेंट को एक-एक करके कंस्ट्रक्टर को पास किया जाएगा। इसलिए, उदाहरण में घोषित पांच एरे निम्नलिखित पांच परिणाम उत्पन्न करते हैं:

यात्रा पहला नंबर दूसरा नंबर अपेक्षित परिणाम कंसोल लाइन
[0] 1 2 3 का योग Numbers = : 3
[1] 11 22 33 का योग Numbers = : 33
[2] 111 222 333 का योग Numbers = : 333
[3] 10 9 19 का योग Numbers = : 19
[4] 100 9 109 का योग Numbers = : 109

चरण 5) पूरा कोड।

इंपोर्ट, कंस्ट्रक्टर, @Parameters मेथड और @Test मेथड सहित AirthematicTest की पूरी लिस्टिंग

Code स्पष्टीकरण:

  • Code रेखा 25: संसाधनों को सेट अप करने के लिए @Before एनोटेशन का उपयोग किया जा रहा है (यहाँ Airthematic.class फ़ाइल का उपयोग किया गया है)। प्रत्येक टेस्ट केस से पहले @Before एनोटेशन का उपयोग किया जाता है। इसमें टेस्ट की पूर्व शर्त शामिल होती है।
  • Code रेखा 36: हम अपने टेस्ट को बनाने के लिए @Test एनोटेशन का उपयोग कर रहे हैं।
  • Code रेखा 39: एक बनाना अभिकथन यह जांचने के लिए कि हमारा योग हमारी अपेक्षा के बराबर है या नहीं।

चरण 6) पैरामीटराइज्ड टेस्ट चलाने के लिए एक टेस्ट रनर क्लास बनाएं:

TestRunner क्लास AirthematicTest.class को पास कर रही है JUnitCore.runClasses और प्रिंटिंग विफलताएँ

Code स्पष्टीकरण:

  • Code रेखा 8: क्लास टेस्ट के मुख्य मेथड को घोषित करना जो हमारे कोड को चलाएगा JUnit परीक्षण.
  • Code रेखा 9: टेस्ट केस निष्पादित करना JUnitCore.runClasses, जो टेस्ट क्लास का नाम एक पैरामीटर के रूप में लेता है (हमारे उदाहरण में हम AirthematicTest.class का उपयोग कर रहे हैं)।
  • Code रेखा 11: परिणाम को फॉर लूप का उपयोग करके संसाधित करना और असफल परिणाम को प्रिंट करना।
  • Code रेखा 13: सफल परिणाम का मुद्रण करना।

आउटपुट:

यह आउटपुट है, जो बिना किसी विफलता के सफल परीक्षण को दर्शाता है। trace, जैसा कि नीचे दिया गया है। ध्यान दें कि JUnit व्यू प्रत्येक डेटा पंक्ति में एक प्रविष्टि को सूचीबद्ध करता है, न कि एक एकल परीक्षण को:

Eclipse JUnit पैरामीटराइज्ड क्लास के लिए रिपोर्टिंग रन 5/5 सफल रहे, जिसमें 0 त्रुटियां और 0 विफलताएं थीं।

कंसोल पर परिणाम देखें, जो दोनों संख्याओं का योग दर्शाता है:

Eclipse कंसोल एक योग प्रिंट कर रहा है Numbers पांचों पैरामीटर पंक्तियों में से प्रत्येक के लिए एक पंक्ति

पैरामीटराइज्ड टेस्ट में JUnit 5 with @ParameterizedTest

ऊपर दिया गया उदाहरण इसके लिए लिखा गया है JUnit 4. JUnit 5 (बृहस्पति) रनर मॉडल को पूरी तरह से हटा देता है, इसलिए @RunWith(Parameterized.class), डेटा कंस्ट्रक्टर और इंस्टेंस फ़ील्ड सभी गायब हो जाते हैं। JUnit ऊपर दिखाया गया कोड अप्रचलित नहीं है: यह अभी भी बिना किसी बदलाव के चलता है। JUnit यह प्लेटफ़ॉर्म पुराने इंजन के माध्यम से काम करता है। हालाँकि, नए परीक्षण आमतौर पर @ParameterizedTest का उपयोग करके लिखे जाते हैं।

दो निर्भरताएँ आवश्यक हैं: परीक्षण एनोटेशन के लिए junit-jupiter-api और junit-jupiter-params पैरामीटराइज्ड सपोर्ट के लिए। दूसरे आर्टिफैक्ट के बिना सोर्स एनोटेशन बिल्कुल भी हल नहीं होंगे।

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

class AirthematicTest {

    // one row per iteration, no constructor and no runner
    @ParameterizedTest(name = "{0} + {1} = {2}")
    @CsvSource({"1, 2, 3", "11, 22, 33", "111, 222, 333", "10, 9, 19", "100, 9, 109"})
    void sumOfTwoNumbers(int firstNumber, int secondNumber, int expectedResult) {
        assertEquals(expectedResult, new Airthematic().sum(firstNumber, secondNumber));
    }
}

बृहस्पति ग्रह तर्क के कई स्रोत प्रदान करता है, और सही स्रोत का चुनाव डेटा के स्वरूप पर निर्भर करता है:

स्रोत एनोटेशन आपूर्ति इसका उपयोग तब करें जब
@ValueSource लिटरल का एक एकल स्तंभ यह परीक्षण केवल एक तर्क लेता है।
@CsvSource पंक्तिबद्ध अल्पविराम-पृथक पंक्तियाँ फ़ाइल में संख्याओं और स्ट्रिंग की छोटी सारणियाँ आसानी से पढ़ी जा सकती हैं।
@CsvFileSource टेस्ट क्लासपाथ पर मौजूद CSV फ़ाइल से पढ़ी गई पंक्तियाँ डेटा सेट बड़ा है या कोड के बाहर बनाए रखा जाता है।
@मेथडसोर्स एक स्टैटिक फ़ैक्टरी जो आर्गुमेंट्स का एक स्ट्रीम लौटाती है वास्तविक वस्तुओं, परिकलित मानों या यादृच्छिक डेटा की आवश्यकता होती है।
@एनमसोर्स एक एनम के स्थिरांक प्रत्येक एनम मान का प्रयोग किया जाना चाहिए

शुरुआती लोगों को दो नियम भ्रमित कर देते हैं। एक साधारण @Test विधि पर लगाया गया स्रोत एनोटेशन अनदेखा कर दिया जाता है, इसलिए विधि में @ParameterizedTest होना आवश्यक है। और @CsvSource में बिना उद्धरण चिह्नों वाला खाली मान नल के रूप में पढ़ा जाता है, जबकि उद्धरण चिह्नों वाला खाली मान एक खाली स्ट्रिंग के रूप में पढ़ा जाता है।

RSI JUnit इस लेख में उपयोग किए गए 4 एनोटेशन बृहस्पति ग्रह पर इस प्रकार मैप होते हैं: @RunWith(Parameterized.class) @ParameterizedTest प्लस एक स्रोत एनोटेशन बन जाता है, @Parameters @MethodSource या @CsvSource बन जाता है, और @Before @BeforeEach बन जाता है। पूरी सूची में शामिल है। JUnit एनोटेशन ट्यूटोरियल।

पैरामीटराइज्ड परीक्षणों के लाभ और सीमाएँ

पैरामीटराइजेशन मुफ्त नहीं है। यह दोहराव को दूर करता है, लेकिन यह परीक्षण लिखने के तरीके को भी सीमित करता है, इसलिए मौजूदा सूट को परिवर्तित करने से पहले इसके दोनों पहलुओं को जानना महत्वपूर्ण है।

फायदे

  • Less दोहराव: एक विधि लगभग एक जैसे असर्ट स्टेटमेंट के एक ब्लॉक को बदल देती है, जैसा कि इस लेख के पहले स्क्रीनशॉट में दिखाया गया है।
  • सस्ता कवरेज: एक एज केस जोड़ने से एक पूरी नई डेटा पंक्ति के बजाय एक अतिरिक्त डेटा पंक्ति की लागत आती है। परीक्षण का मामला विधि.
  • सटीक रिपोर्टिंग: प्रत्येक पुनरावृति की रिपोर्ट अलग से दी जाती है, इसलिए JUnit यह व्यू किसी एक समग्र विफलता के बजाय, ठीक-ठीक यह पहचान करता है कि कौन सी पंक्ति विफल हुई है।
  • केंद्रीकृत डेटा: इनपुट एक ही मेथड में रहते हैं और बाद में उन्हें असर्शन को छुए बिना CSV फ़ाइल या फ़ैक्टरी में ले जाया जा सकता है।

सीमाओं

  • अभिकथन का एक रूप: प्रत्येक पंक्ति समान अभिकथन चलाती है, इसलिए जिस परिदृश्य में अलग-अलग जांच की आवश्यकता होती है, उसके लिए अभी भी अपनी अलग परीक्षण विधि की आवश्यकता होती है।
  • कक्षा-स्तर का दायरा JUnit 4: रनर पूरी क्लास को पैरामीटराइज़ करता है, इसलिए उस क्लास में असंबंधित @Test मेथड भी प्रति पंक्ति एक बार चलते हैं।
  • अपठनीय रिपोर्टें: नाम टेम्पलेट के बिना, विफलताएं testAirthematicTest[3] के रूप में दिखाई देती हैं, जो उस डेटा के बारे में कुछ नहीं कहती है जो टूट गया है।
  • भारी इनलाइन डेटा: बड़े एरे टेस्ट लॉजिक को बाधित करते हैं; इसके बजाय उन्हें @CsvFileSource या @MethodSource फ़ैक्टरी में ले जाएं।

सामान्य त्रुटियाँ JUnit पैरामीटराइज्ड टेस्ट

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

मैसेज कारण फिक्स
टेस्ट क्लास में ठीक एक ही पब्लिक कंस्ट्रक्टर होना चाहिए। यह क्लास किसी भी सार्वजनिक कंस्ट्रक्टर की घोषणा नहीं करती है, या फिर दो सार्वजनिक कंस्ट्रक्टर घोषित करती है। एक सार्वजनिक कंस्ट्रक्टर रखें जिसके पैरामीटर डेटा कॉलम से मेल खाते हों।
क्लास पर कोई सार्वजनिक स्थिर पैरामीटर विधि नहीं है @Parameters विधि सार्वजनिक स्थिर नहीं है, या गलत प्रकार लौटाती है। इसे पब्लिक स्टैटिक कलेक्शन के रूप में घोषित करें और Arrays.asList(…) रिटर्न करें।
IllegalArgumentException: तर्कों की संख्या गलत है एक पंक्ति कंस्ट्रक्टर पैरामीटर सूची से चौड़ी या संकरी होती है। कलेक्शन में मौजूद प्रत्येक ऐरे की चौड़ाई कंस्ट्रक्टर के समान रखें।
कॉन्फ़िगरेशन त्रुटि: कोई तर्क प्रदाता नहीं जुपिटर टेस्ट में @ParameterizedTest होता है जिसमें कोई सोर्स एनोटेशन नहीं होता है। @ValueSource, @CsvSource, @CsvFileSource, @MethodSource या @EnumSource जोड़ें
स्रोत एनोटेशन का कोई प्रभाव नहीं दिखता। इस विधि में @ParameterizedTest के बजाय @Test एनोटेशन का उपयोग किया गया है। @Test को @ParameterizedTest से बदलें और junit-jupiter-params को इम्पोर्ट करें।

एक और समस्या साझा अवस्था है। क्योंकि JUnit प्रत्येक पंक्ति के लिए एक नया इंस्टेंस बनाता है, स्टैटिक फ़ील्ड में रखी गई कोई भी चीज़ प्रत्येक पुनरावृति में बनी रहती है, और पंक्ति [0] द्वारा लिखा गया मान पंक्ति [4] के परिणाम को चुपचाप बदल सकता है। प्रति-पंक्ति स्थिति को इंस्टेंस फ़ील्ड में रखें और @Before या @BeforeEach विधि में साझा संसाधनों को रीसेट करें। परीक्षणों को अलग करने पर सामान्य मार्गदर्शन इसमें शामिल है। इकाई का परीक्षण ट्यूटोरियल।

अक्सर पूछे जाने वाले प्रश्न

TestNG यह प्रत्येक परीक्षण विधि द्वारा संदर्भित @DataProvider विधि के माध्यम से पंक्तियाँ प्रदान करता है, इसलिए क्लास में असंबंधित परीक्षण अप्रभावित रहते हैं। JUnit 4 अपने रनर के माध्यम से पूरी क्लास को पैरामीटराइज़ करता है। JUnit 5 प्रति-विधि @ParameterizedTest के साथ उस अंतर को बंद करता है।

हां. JUnit 4 @Parameters(name = “{index}: sum({0},{1})={2}”) को स्वीकार करता है और Jupiter @ParameterizedTest(name = “…”) को स्वीकार करता है। प्लेसहोल्डर रनटाइम पर बदल दिए जाते हैं, इसलिए विफलता रिपोर्ट में केवल इंडेक्स दिखाने के बजाय त्रुटिपूर्ण पंक्ति का नाम दिया जाता है।

हां. JUnit 4 सार्वजनिक गैर-स्थैतिक फ़ील्ड पर @Parameter(0) और @Parameter(1) का समर्थन करता है, और फिर क्लास डिफ़ॉल्ट कंस्ट्रक्टर पर निर्भर करता है। फ़ील्ड इंजेक्शन को डेटा कंस्ट्रक्टर के साथ संयोजित करने से ठीक-एक-सार्वजनिक-कंस्ट्रक्टर त्रुटि उत्पन्न होती है।

JUnit 4 को केवल ज्यूनिट आर्टिफैक्ट की आवश्यकता होती है, क्योंकि पैरामीटराइज्ड रनर इसके भीतर ही आता है। JUnit 5 को junit-jupiter-api के साथ junit-jupiter-params की आवश्यकता होती है; उस आर्टिफैक्ट के बिना @ParameterizedTest और हर स्रोत एनोटेशन हल करने में विफल हो जाते हैं।

Jupiter @CsvFileSource(resources = “/data.csv”, numLinesToSkip = 1) प्रदान करता है, जो परीक्षण क्लासपाथ से पंक्तियों को पढ़ता है। JUnit 4 का कोई अंतर्निहित समकक्ष नहीं है, इसलिए @Parameters विधि को कलेक्शन लौटाने से पहले फ़ाइल को स्वयं खोलना और पार्स करना होगा।

In JUnit 4. यह संभव है, लेकिन रनर पूरी क्लास को पैरामीटराइज़ करता है, इसलिए प्रत्येक विधि प्रति डेटा पंक्ति एक बार चलती है। जुपिटर व्यक्तिगत विधियों को पैरामीटराइज़ करता है, इसलिए एक ही क्लास में सामान्य @Test विधियाँ अभी भी ठीक एक बार ही निष्पादित होती हैं।

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

गिटहब कोपिलॉट यह ढांचा जल्दी तैयार करता है लेकिन अक्सर मिश्रण करता है JUnit 4 और जुपिटर इंपोर्ट्स, कभी-कभी एक साधारण @Test मेथड पर सोर्स एनोटेशन छोड़ देते हैं। सूट चलाने से पहले इंपोर्ट्स की जांच कर लें।

इस पोस्ट को संक्षेप में इस प्रकार लिखें: