निश्चित रूप से हर कोई
परीक्षण-संचालित विकास (टीडीडी) की अवधारणा से परिचित है। इसके साथ,
डेटा-संचालित परीक्षण (डीडीटी, शेवचुक के लिए कोई अपराध नहीं) जैसी कोई चीज भी है - परीक्षण लिखने के लिए एक तकनीक जिसमें परीक्षणों के लिए डेटा स्वयं परीक्षणों से अलग संग्रहीत होता है। उन्हें परीक्षण निष्पादन के दौरान उत्पन्न डेटाबेस, फ़ाइल में संग्रहीत किया जा सकता है। यह बहुत सुविधाजनक है, क्योंकि एक ही कार्यक्षमता को विभिन्न डेटा सेटों पर परीक्षण किया जाता है, जबकि इस डेटा को जोड़ना, हटाना या बदलना अधिकतम सरलीकृत है।
पिछले लेख में, मैंने
JUnit की क्षमताओं की जांच की।
पैरामीटर और
थ्योरी लॉन्चर इस दृष्टिकोण के उदाहरण के रूप में काम कर सकते हैं, दोनों ही मामलों में एक टेस्ट क्लास में केवल एक ही ऐसा पैरामीटराइज्ड टेस्ट (
Parameterized कई के मामले में हो सकता है, लेकिन वे सभी एक ही डेटा का उपयोग करेंगे)।
इस लेख में, मैं
TestNG परीक्षण ढांचे पर ध्यान केंद्रित करूंगा। कई लोग इस नाम को पहले ही सुन चुके हैं, और इसे बंद करने के बाद, वे शायद ही जेयूनिट में वापस जाना चाहते हैं (हालाँकि यह केवल एक धारणा है)।
मुख्य विशेषताएं
तो वहाँ क्या है? जेयूनीट 4 की तरह, परीक्षणों में एनोटेशन का उपयोग किया जाता है, और जेयूनिट 3 में लिखे गए परीक्षणों का भी समर्थन किया जाता है। एनोटेशन के बजाय डॉकलेट का उपयोग करना संभव है।
शुरू करने के लिए, परीक्षणों के पदानुक्रम पर विचार करें। सभी परीक्षण किसी भी परीक्षण अनुक्रम (सुइट) से संबंधित हैं, इसमें कई कक्षाएं शामिल हैं, जिनमें से प्रत्येक में कई परीक्षण विधियां शामिल हो सकती हैं। इसके अलावा, कक्षाएं और परीक्षण विधियां एक निश्चित समूह से संबंधित हो सकती हैं। यह नेत्रहीन इस तरह दिखता है:
+- suite/ +- test0/ | +- class0/ | | +- method0(integration group)/ | | +- method1(functional group)/ | | +- method2/ | +- class1 | +- method3(optional group)/ +- test1/ +- class3(optional group, integration group)/ +- method4/
इस पदानुक्रम का प्रत्येक सदस्य विन्यासकर्ताओं के
पहले और
बाद में हो सकता है। यह इस क्रम में सभी शुरू होता है:
+- before suite/ +- before group/ +- before test/ +- before class/ +- before method/ +- test/ +- after method/ ... +- after class/ ... +- after test/ ... +- after group/ ... +- after suite/
अब परीक्षणों के बारे में और अधिक। एक उदाहरण पर विचार करें। उन स्थानों के साथ काम करने की उपयोगिता जो स्ट्रिंग से पार्स कर सकते हैं, साथ ही उम्मीदवारों की खोज कर सकते हैं (
en_US -> en_US, en, root ):
public abstract class LocaleUtils { public static final Locale ROOT_LOCALE = new Locale(""); private static final String LOCALE_SEPARATOR = "_"; public static Locale parseLocale(final String value) { if (value != null) { final StringTokenizer tokens = new StringTokenizer(value, LOCALE_SEPARATOR); final String language = tokens.hasMoreTokens() ? tokens.nextToken() : ""; final String country = tokens.hasMoreTokens() ? tokens.nextToken() : ""; String variant = ""; String sep = ""; while (tokens.hasMoreTokens()) { variant += sep + tokens.nextToken(); sep = LOCALE_SEPARATOR; } return new Locale(language, country, variant); } return null; } public static List<Locale> getCandidateLocales(final Locale locale) { final List<Locale> locales = new ArrayList<Locale>(); if (locale != null) { final String language = locale.getLanguage(); final String country = locale.getCountry(); final String variant = locale.getVariant(); if (variant.length() > 0) { locales.add(locale); } if (country.length() > 0) { locales.add((locales.size() == 0) ? locale : new Locale(language, country)); } if (language.length() > 0) { locales.add((locales.size() == 0) ? locale : new Locale(language)); } } locales.add(ROOT_LOCALE); return locales; } }
हम JUnit-a की शैली में एक परीक्षण लिखेंगे (हमें इस उदाहरण को TestN पर परीक्षण लिखने के लिए एक मार्गदर्शक के रूप में नहीं समझना चाहिए):
public class LocaleUtilsOldStyleTest extends Assert { private final Map<String, Locale> parseLocaleData = new HashMap<String, Locale>(); @BeforeClass private void setUp() { parseLocaleData.put(null, null); parseLocaleData.put("", LocaleUtils.ROOT_LOCALE); parseLocaleData.put("en", Locale.ENGLISH); parseLocaleData.put("en_US", Locale.US); parseLocaleData.put("en_GB", Locale.UK); parseLocaleData.put("ru", new Locale("ru")); parseLocaleData.put("ru_RU_xxx", new Locale("ru", "RU", "xxx")); } @AfterTest void tearDown() { parseLocaleData.clear(); } @Test public void testParseLocale() { for (Map.Entry<String, Locale> entry : parseLocaleData.entrySet()) { final Locale actual = LocaleUtils.parseLocale(entry.getKey()); final Locale expected = entry.getValue(); assertEquals(actual, expected); } } }
वहाँ क्या है?
- जैसा कि पिछले लेख में पहले ही उल्लेख किया गया है, मैं परख कक्षा से वारिस लेना पसंद करता हूं, इसे स्थैतिक आयात से बदला जा सकता है, या सीधे कक्षा का उपयोग करके ( Assert.assertEquals (...) ) किया जा सकता है। एक वास्तविक प्रणाली में, कुछ बेस क्लास से एक टेस्ट इनहेरिट करना सबसे सुविधाजनक है, जो बदले में, एसेरल से विरासत में मिला है, इससे आवश्यक तरीकों को ओवरराइड या जोड़ना संभव हो जाता है। नोट: JUnit में एक ही वर्ग के विपरीत, यहाँ, सभी तरीकों में, वर्तमान मूल्य पहले पारित किया गया है, दूसरा (JUnit में इसके विपरीत) द्वारा अपेक्षित है।
- नोटिफिकेशन @BeforeSuite , @AfterSuite उन तरीकों को दर्शाती है , जिन्हें सभी परीक्षणों से पहले / बाद में निष्पादित किया जाता है। किसी भी भारी सेटिंग को सभी परीक्षणों के लिए सामान्य रखना सुविधाजनक है, उदाहरण के लिए, यहां आप डेटाबेस से कनेक्शन का एक पूल बना सकते हैं।
- टिप्पणियां @BeforeTest , @AfterTest निरूपित विधियों को परीक्षण से पहले / बाद में निष्पादित किया जाता है (जिसमें परीक्षण कक्षाएं शामिल हैं उन्हें परीक्षण विधियों के साथ भ्रमित नहीं किया जाना चाहिए)। यहां आप इंटरकनेक्टेड सेवाओं के किसी भी समूह की सेटिंग्स, या एक सेवा को स्टोर कर सकते हैं, अगर यह कई परीक्षण कक्षाओं द्वारा परीक्षण किया जाता है।
- एनोटेशन @BeforeClass , @AfterClass उन तरीकों को निरूपित करते हैं जो कक्षा में सभी परीक्षणों से पहले / बाद में निष्पादित किए गए हैं, पिछले वाले के समान हैं, लेकिन परीक्षण कक्षाओं पर लागू होते हैं। यह एक विशिष्ट सेवा के परीक्षण के लिए सबसे अधिक लागू होता है जो परीक्षण के परिणामस्वरूप अपने राज्य को नहीं बदलता है।
- नोटिफिकेशन @BeforeMethod , @AfterMethod उन तरीकों को निरूपित करते हैं जो हर बार परीक्षण विधि से पहले / बाद में निष्पादित किए जाते हैं। यहां एक विशिष्ट बीन या सेवा के लिए सेटिंग्स को स्टोर करना सुविधाजनक है अगर यह परीक्षण के परिणामस्वरूप अपनी स्थिति को नहीं बदलता है।
- एनोटेशन @BeforeGroups , @AfterGroups दिए गए समूहों से पहले / अंतिम परीक्षण से पहले / बाद में निष्पादित होने वाले तरीकों को दर्शाता है।
- @ टेस्ट एनोटेशन से तात्पर्य स्वयं परीक्षणों से है। चेक यहां रखे गए हैं। कक्षाओं के लिए भी लागू है।
इन सभी एनोटेशन में निम्नलिखित विकल्प हैं:
- सक्षम - मूल्य को गलत पर सेट करके अस्थायी रूप से अक्षम किया जा सकता है
- समूह - इंगित करता है कि किन समूहों को निष्पादित किया जाएगा
- inheritGroups - यदि सही (और डिफ़ॉल्ट रूप से इस तरह), विधि परीक्षण वर्ग से समूहों को इनहेरिट करेगी
- समय - समय जिसके बाद विधि "गिर जाएगी" और उस पर निर्भर सभी परीक्षण खींच लेंगे
- विवरण - रिपोर्ट में प्रयुक्त नाम
- निर्भरऑनमेथोड्स - जिन तरीकों पर यह निर्भर करता है, पहले उन्हें निष्पादित किया जाएगा, और फिर यह विधि
- dependones समूह - जिन पर निर्भर करता है
- हमेशा - अगर यह सच है, तो इसे हमेशा कोई भी बात नहीं कहा जाएगा कि यह किस समूह से संबंधित है, यह @BeforeGroups , @AfterGroups पर लागू नहीं होता है
जैसा कि आप उदाहरण से देख सकते हैं, परीक्षण व्यावहारिक रूप से JUnit पर एक ही परीक्षण से अलग नहीं है। अगर कोई अंतर नहीं है, तो टेस्टएनजी का उपयोग क्यों करें?
परिमार्जित परीक्षण
आइए एक ही परीक्षा को दूसरे तरीके से लिखें:
public class LocaleUtilsTest extends Assert { @DataProvider public Object[][] parseLocaleData() { return new Object[][]{ {null, null}, {"", LocaleUtils.ROOT_LOCALE}, {"en", Locale.ENGLISH}, {"en_US", Locale.US}, {"en_GB", Locale.UK}, {"ru", new Locale("ru")}, {"ru_RU_some_variant", new Locale("ru", "RU", "some_variant")}, }; } @Test(dataProvider = "parseLocaleData") public void testParseLocale(String locale, Locale expected) { final Locale actual = LocaleUtils.parseLocale(locale); assertEquals(actual, expected); } }
आसान? बेशक, डेटा को परीक्षण से ही अलग से संग्रहीत किया जाता है। क्या यह सुविधाजनक है? बेशक, आप parseLocaleData विधि में सिर्फ एक पंक्ति जोड़कर परीक्षण जोड़ सकते हैं।
तो यह कैसे काम करता है?
- हम सभी मापदंडों के साथ एक परीक्षण विधि की घोषणा करते हैं, उदाहरण के लिए, इनपुट और अपेक्षित डेटा। हमारे मामले में, यह एक स्ट्रिंग है जिसे परिणामस्वरूप लोकेल और अपेक्षित लोकेल में पार्स करने की आवश्यकता है।
- हम प्रदाता की तिथि, परीक्षण के लिए डेटा वेयरहाउस की घोषणा करते हैं। यह आमतौर पर एक विधि होती है जो ऑब्जेक्ट [] [] या Iterator <ऑब्जेक्ट []> में एक विशेष परीक्षण के लिए मापदंडों की एक सूची होती है, उदाहरण के लिए {"en_US", Locale.US} । इस विधि को @DataProvider का उपयोग करके एनोटेट किया जाना चाहिए, परीक्षण में यह @Test एनोटेशन में dataProvider पैरामीटर का उपयोग करके घोषित किया गया है। आप एक नाम (पैरामीटर नाम ) भी निर्दिष्ट कर सकते हैं, यदि आप विधि का नाम निर्दिष्ट नहीं करते हैं, तो विधि नाम का उपयोग किया जाएगा।
एक और उदाहरण, अब हम परीक्षण के डेटा और तर्क को विभिन्न वर्गों में फैलाएंगे:
public class LocaleUtilsTestData { @DataProvider(name = "getCandidateLocalesData") public static Object[][] getCandidateLocalesData() { return new Object[][]{ {null, Arrays.asList(LocaleUtils.ROOT_LOCALE)}, {LocaleUtils.ROOT_LOCALE, Arrays.asList(LocaleUtils.ROOT_LOCALE)}, {Locale.ENGLISH, Arrays.asList(Locale.ENGLISH, LocaleUtils.ROOT_LOCALE)}, {Locale.US, Arrays.asList(Locale.US, Locale.ENGLISH, LocaleUtils.ROOT_LOCALE)}, {new Locale("en", "US", "xxx"), Arrays.asList( new Locale("en", "US", "xxx"), Locale.US, Locale.ENGLISH, LocaleUtils.ROOT_LOCALE) }, }; } } public class LocaleUtilsTest extends Assert {
इस स्थिति में, पैरामीटर
डेटाप्रोवाइडरक्लास और
डेटाप्रोवाइडर सेट होते हैं । परीक्षण डेटा लौटने की विधि
स्थिर होनी चाहिए।
उपरोक्त के अलावा, परीक्षणों को मानकीकृत करने का एक और तरीका है। वांछित विधि
@ पैरामीटर का उपयोग करके एनोटेट की
जाती है , जहां सभी आवश्यक मापदंडों के नाम इंगित किए जाते हैं। कुछ मापदंडों को डिफ़ॉल्ट मान के साथ
@ वैकल्पिक का उपयोग करके एनोटेट किया जा सकता है (यदि निर्दिष्ट नहीं है, तो प्राइमेट के लिए डिफ़ॉल्ट मान का उपयोग किया जाएगा, या अन्य सभी प्रकारों के लिए शून्य)। पैरामीटर मान TestNG कॉन्फ़िगरेशन (जिसे बाद में चर्चा की जाएगी) में संग्रहीत किया जाता है। एक उदाहरण:
public class ParameterizedTest extends Assert { private DataSource dataSource; @Parameters({"driver", "url", "username", "password"}) @BeforeClass public void setUpDataSource(String driver, String url, @Optional("sa") String username, @Optional String password) {
इस मामले में,
setUpDataSource विधि डेटाबेस कनेक्शन सेटिंग्स को मापदंडों के रूप में स्वीकार करेगी, और
उपयोगकर्ता नाम और
पासवर्ड पैरामीटर वैकल्पिक हैं, दिए गए डिफ़ॉल्ट मानों के साथ। सभी परीक्षणों (अच्छी तरह से, या लगभग सभी) के लिए डेटा के साथ उपयोग करना बहुत सुविधाजनक है, उदाहरण के लिए, डेटाबेस कनेक्शन स्थापित करने के उदाहरण में।
खैर, निष्कर्ष में, कारखानों के बारे में कुछ शब्द कहा जाना चाहिए जो आपको गतिशील रूप से परीक्षण बनाने की अनुमति देते हैं। स्वयं परीक्षणों के साथ-साथ, उन्हें
@DataProvider या
@Parameters का उपयोग करके
परिमाणित किया जा सकता है:
public class FactoryTest { @DataProvider public Object[][] tablesData() { return new Object[][] { {"FIRST_TABLE"}, {"SECOND_TABLE"}, {"THIRD_TABLE"}, }; } @Factory(dataProvider = "tablesData") public Object[] createTest(String table) { return new Object[] { new GenericTableTest(table) }; } } public class GenericTableTest extends Assert { private final String table; public GenericTableTest(final String table) { this.table = table; } @Test public void testTable() { System.out.println(table);
@ पैरामीटर्स के साथ विकल्प:
public class FactoryTest { @Parameters("table") @Factory public Object[] createParameterizedTest(@Optional("SOME_TABLE") String table) { return new Object[] { new GenericTableTest(table) }; } }
बहु सूत्रण
यह जांचने की आवश्यकता है कि एप्लिकेशन बहु-थ्रेडेड वातावरण में कैसे व्यवहार करता है? आप कई थ्रेड्स से एक साथ परीक्षण चला सकते हैं:
public class ConcurrencyTest extends Assert { private Map<String, String> data; @BeforeClass void setUp() throws Exception { data = new HashMap<String, String>(); } @AfterClass void tearDown() throws Exception { data = null; } @Test(threadPoolSize = 30, invocationCount = 100, invocationTimeOut = 10000) public void testMapOperations() throws Exception { data.put("1", "111"); data.put("2", "111"); data.put("3", "111"); data.put("4", "111"); data.put("5", "111"); data.put("6", "111"); data.put("7", "111"); for (Map.Entry<String, String> entry : data.entrySet()) { System.out.println(entry); } data.clear(); } @Test(singleThreaded = true, invocationCount = 100, invocationTimeOut = 10000) public void testMapOperationsSafe() throws Exception { data.put("1", "111"); data.put("2", "111"); data.put("3", "111"); data.put("4", "111"); data.put("5", "111"); data.put("6", "111"); data.put("7", "111"); for (Map.Entry<String, String> entry : data.entrySet()) { System.out.println(entry); } data.clear(); } }
- थ्रेडपूलसाइज़ परीक्षणों के लिए उपयोग किए जाने वाले थ्रेड्स की अधिकतम संख्या निर्धारित करता है।
- सिंगल थ्रेडेड यदि सही पर सेट किया जाता है, तो सभी परीक्षण एक ही थ्रेड पर चलाए जाएंगे।
- मंगलाचरण टेस्ट रन की संख्या निर्धारित करता है।
- InvocationTimeOut सभी टेस्ट रन का कुल समय निर्धारित करता है, जिसके बाद परीक्षण विफल माना जाता है।
पहला परीक्षण समय-समय पर
समवर्ती विफल हो जाएगा, क्योंकि यह विभिन्न थ्रेड्स से चलाया जाएगा, दूसरा नहीं होगा, क्योंकि सभी परीक्षण एक धागे से क्रमिक रूप से चलाए जाएंगे।
आप प्रदाता तिथि के
समानांतर पैरामीटर को भी सही पर सेट कर सकते हैं, फिर प्रत्येक डेटा सेट के लिए परीक्षण समानांतर में लॉन्च किए जाएंगे, एक अलग संख्या में:
public class ConcurrencyTest extends Assert {
यह परीक्षण कुछ इस तरह उत्पादन करेगा:
#16 pool-1-thread-3: 5 : 6 #19 pool-1-thread-6: 11 : 12 #14 pool-1-thread-1: 1 : 2 #22 pool-1-thread-9: 17 : 18 #20 pool-1-thread-7: 13 : 14 #18 pool-1-thread-5: 9 : 10 #15 pool-1-thread-2: 3 : 4 #17 pool-1-thread-4: 7 : 8 #21 pool-1-thread-8: 15 : 16 #23 pool-1-thread-10: 19 : 20
इस पैरामीटर के बिना, कुछ ऐसा होगा:
#1 main: 1 : 2 #1 main: 3 : 4 #1 main: 5 : 6 #1 main: 7 : 8 #1 main: 9 : 10 #1 main: 11 : 12 #1 main: 13 : 14 #1 main: 15 : 16 #1 main: 17 : 18 #1 main: 19 : 20
अतिरिक्त विशेषताएं
वर्णित सब कुछ के अलावा, अन्य संभावनाएं हैं, उदाहरण के लिए, अपवादों को फेंकने की जांच करने के लिए (यह गलत डेटा पर परीक्षणों के लिए उपयोग करने के लिए बहुत सुविधाजनक है):
public class ExceptionTest { @DataProvider public Object[][] wrongData() { return new Object[][] { {"Hello, World!!!"}, {"0x245"}, {"1798237199878129387197238"}, }; } @Test(dataProvider = "wrongData", expectedExceptions = NumberFormatException.class, expectedExceptionsMessageRegExp = "^For input string: \"(.*)\"$") public void testParse(String data) { Integer.parseInt(data); } }
- अपेक्षित अपवाद अपवादों के लिए विकल्प सेट करते हैं; यदि उन्हें फेंका नहीं गया है, तो परीक्षण विफल माना जाता है।
- अपेक्षित अपवाद .MessageRegExp पिछले पैरामीटर के समान है, लेकिन त्रुटि संदेश के लिए regexp सेट करता है।
एक और उदाहरण:
public class PrioritiesTest extends Assert { private boolean firstTestExecuted; @BeforeClass public void setUp() throws Exception { firstTestExecuted = false; } @Test(priority = 0) public void first() { assertFalse(firstTestExecuted); firstTestExecuted = true; } @Test(priority = 1) public void second() { assertTrue(firstTestExecuted); } }
- प्राथमिकता कक्षा के अंदर परीक्षण की प्राथमिकता निर्धारित करती है, पहले जितना छोटा होगा उसे निष्पादित किया जाएगा।
यह उदाहरण सफल होगा क्योंकि पहला तरीका
पहले निष्पादित करेगा, फिर
दूसरा । यदि आप
पहली से 2 की प्राथमिकता बदलते हैं, तो परीक्षण विफल हो जाएगा।
एक समान व्यवहार भी देखा जाएगा यदि आप परीक्षण की निर्भरता निर्दिष्ट करते हैं, उदाहरण के लिए, हमारे परीक्षण में जोड़ें:
public class PrioritiesTest extends Assert {
यह आमतौर पर सुविधाजनक होता है जब एक परीक्षण दूसरे पर निर्भर करता है, उदाहरण के लिए,
यूटिलिटी 1 यूटिलिटी 0 का उपयोग करता है, अगर
यूटिलिटी 0 सही ढंग से काम नहीं करता है, तो यह
यूटिलिटी 1 का परीक्षण करने के लिए कोई मतलब नहीं है। दूसरी ओर, यह
@Before ,
@ तरीकों में निर्भरता का उपयोग करने के लिए भी सुविधाजनक है, विशेष रूप से मूल परीक्षण को विरासत में मिली के साथ जोड़ने के लिए, और कभी-कभी यह सुनिश्चित करना आवश्यक है कि भले ही विधि
ए विफल हो और विधि
बी इस पर निर्भर करती है, विधि
बी को अभी भी कहा जाता है। इस स्थिति में,
हमेशा पैरामीटर पैरामीटर को सही पर सेट करें।
निर्भरता इंजेक्शन
मैं "अच्छे निगम"
गुइसे से ढांचे के प्रशंसकों को खुश करना चाहता हूं। TestNG ने बाद के लिए अंतर्निहित समर्थन किया है। यह इस तरह दिखता है:
public class GuiceModule extends AbstractModule { @Override protected void configure() { bind(String.class).annotatedWith(Names.named("guice-string-0")).toInstance("Hello, "); } @Named("guice-string-1") @Inject @Singleton @Provides public String provideGuiceString() { return "World!!!"; } } @Guice(modules = {GuiceModule.class}) public class GuiceTest extends Assert { @Inject @Named("guice-string-0") private String word0; @Inject @Named("guice-string-1") private String word1; @Test public void testService() { final String actual = word0 + word1; assertEquals(actual, "Hello, World!!!"); } }
सभी आवश्यक है कि
@Guice का उपयोग करके आवश्यक वर्ग को एनोटेट करें और मॉड्यूल पैरामीटर में सभी आवश्यक
गार्ड मॉड्यूल निर्दिष्ट करें। परीक्षण वर्ग में आगे, आप पहले से ही
@ इंजेक्शन का उपयोग करके निर्भरता इंजेक्शन का उपयोग कर
सकते हैं ।
मैं यह भी जोड़ता हूं कि अन्य समान रूपरेखा के प्रशंसकों को परेशान नहीं होना चाहिए, क्योंकि आमतौर पर टेस्टएनजी के लिए उनका अपना समर्थन होता है, उदाहरण के लिए, वसंत।
कार्यक्षमता विस्तार
श्रोता तंत्र का उपयोग करके कार्यात्मक विस्तार को लागू किया जा सकता है। निम्नलिखित श्रोता प्रकार समर्थित हैं:
- IAnnotationTransformer, IAnnotationTransformer2 - आपको परीक्षण सेटिंग्स को ओवरराइड करने की अनुमति देता है, उदाहरण के लिए, परीक्षण चलाने के लिए थ्रेड्स की संख्या, टाइमआउट, अपेक्षित अपवाद:
public class ExpectTransformer implements IAnnotationTransformer { public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { if (testMethod.getName().startsWith("expect")) { annotation.setExpectedExceptions(new Class[] {Exception.class}); } } }
यह उदाहरण उम्मीद से शुरू होने वाले परीक्षण तरीकों से एक अपवाद को फेंकने की उम्मीद करेगा। - IHookable - आपको परीक्षण विधि को ओवरराइड करने की अनुमति देता है या संभवतः छोड़ देता है, ट्यूटोरियल में TestNG को JAAS के साथ एक उदाहरण प्रदान किया गया है।
- IInvokedMethodListener, IInvokedMethodListener2 - पिछले श्रोता के समान है, लेकिन परीक्षण विधि के निष्पादन से पहले और बाद में कोड निष्पादित करता है
- IMethodInterceptor - आपको उस क्रम को बदलने की अनुमति देता है जिसमें परीक्षण चलाए जाते हैं (केवल उन परीक्षणों पर लागू होते हैं जो अन्य परीक्षणों से स्वतंत्र हैं)। ट्यूटोरियल में एक अच्छा उदाहरण है।
- IReporter - आपको सभी परीक्षणों के पूरा होने के बाद की जाने वाली कार्यक्षमता का विस्तार करने की अनुमति देता है, आमतौर पर यह कार्यक्षमता जनरेशन की त्रुटि रिपोर्ट आदि से जुड़ी होती है। इस प्रकार, आप अपने रिपोर्टिंग इंजन को लागू कर सकते हैं।
- ITestListener - एक श्रोता जो परीक्षण विधि से अधिकांश घटनाओं को संभाल सकता है, उदाहरण के लिए, प्रारंभ, खत्म, सफलता, विफलता
- ISuiteListener - पिछले एक के समान है, लेकिन सुइट्स के लिए, केवल शुरुआत और समापन कार्यक्रम प्राप्त करता है
आप
यहां श्रोता तंत्र के एक दिलचस्प उपयोग के एक उदाहरण के बारे में पढ़ सकते हैं।
विन्यास
अब हम परीक्षण कॉन्फ़िगरेशन पर चलते हैं। परीक्षण चलाने का सबसे सरल तरीका कुछ इस प्रकार है:
final TestNG testNG = new TestNG(true); testNG.setTestClasses(new Class[] {SuperMegaTest.class}); testNG.setExcludedGroups("optional"); testNG.run();
लेकिन सबसे अधिक बार, XML या YAML कॉन्फ़िगरेशन का उपयोग परीक्षण चलाने के लिए किया जाता है। XML कॉन्फ़िगरेशन कुछ इस तरह दिखता है:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Test suite" parallel="classes" thread-count="10"> <test name="Default tests" verbose="1" annotations="JDK" thread-count="10" parallel="classes"> <parameter name="driver" value="com.mysql.jdbc.Driver"/> <parameter name="url" value="jdbc:mysql://localhost:3306/db"/> <groups> <run> <exclude name="integration"/> </run> </groups> <packages> <package name="com.example.*"/> </packages> </test> <test name="Integration tests" annotations="JDK"> <groups> <run> <include name="integration"/> </run> </groups> <packages> <package name="com.example.*"/> </packages> </test> </suite>
इसी तरह के YAML कॉन्फ़िगरेशन:
name: YAML Test suite parallel: classes threadCount: 10 tests: - name: Default tests parameters: driver: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/db excludedGroups: [ integration ] packages: - com.example.* - name: Integration tests parameters: driver: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/db includedGroups: [ integration ] packages: - com.example.*
फिर परीक्षण चलाने के लिए आपको निम्नलिखित कार्य करने होंगे:
final TestNG testNG = new TestNG(true);
हालांकि, शायद, प्रोग्रामेटिक रूप से चल रहे परीक्षण अनावश्यक हैं, क्योंकि आप इसके लिए आईडीई की क्षमताओं का उपयोग कर सकते हैं।
आइए कॉन्फ़िगरेशन पर वापस जाएं। उच्चतम स्तर पर, एक परीक्षण अनुक्रम (सुइट) स्थापित किया गया है। यह निम्नलिखित पैरामीटर ले सकता है:
- नाम - रिपोर्ट में प्रयुक्त नाम
- थ्रेड-काउंट - थ्रेड्स की संख्या परीक्षण चलाने के लिए उपयोग की जाती है
- डेटा-प्रदाता-थ्रेड-काउंट - समानांतर डेटा प्रदाताओं ( @DataProvider (समानांतर = सत्य) ) के लिए डेटा प्रदाताओं से परीक्षण के लिए स्वयं डेटा स्थानांतरित करने के लिए उपयोग किए जाने वाले थ्रेड्स की संख्या
- समानांतर - निम्नलिखित मान ले सकते हैं:
- विधियाँ - परीक्षण विधियाँ विभिन्न थ्रेड्स में चलाई जाएंगी, यदि विधियों के बीच निर्भरता हो तो आपको सावधान रहने की आवश्यकता है
- कक्षाएं - एक धागे में एक ही कक्षा की सभी विधियाँ, लेकिन विभिन्न वर्गों में अलग-अलग कक्षाएं
- परीक्षण - एक धागे में एक परीक्षण के सभी तरीके, विभिन्न धागे में विभिन्न परीक्षण
- टाइम-आउट - वह समय जिसके बाद परीक्षण विफल माना जाएगा, एनोटेशन में भी, लेकिन सभी परीक्षण विधियों पर लागू होता है
- junit - JUnit 3 परीक्षण
- एनोटेशन - अगर javadoc, तो doclet कॉन्फ़िगरेशन के लिए उपयोग किया जाएगा
भी कॉन्फ़िगर किया जा सकता है:
- पैरामीटर - @ पैरामीटर द्वारा उपयोग किए जाने वाले पैरामीटर
- पैकेज - पैकेज जहां परीक्षण कक्षाओं के लिए देखना है
- श्रोता - श्रोता, उनकी मदद से TestNG की कार्यक्षमता का विस्तार करना संभव है, मैंने पहले ही उनके बारे में कुछ शब्द कहे हैं
- विधि-चयनकर्ता - परीक्षणों के लिए चयनकर्ता, IMethodSelector इंटरफ़ेस को लागू करना चाहिए
- सुइट-फाइलें - आप अन्य कॉन्फ़िगरेशन फ़ाइलों को शामिल कर सकते हैं
सूट, बदले में, सूट (
नाम, धागा-गणना, समानांतर, टाइम-आउट, जूनिट, एनोटेशन ,
पैरामीटर, पैकेज, विधि-चयनकर्ता टैग) के लिए लगभग समान सेटिंग्स के साथ परीक्षण शामिल कर सकते हैं। टेस्ट में अजीबोगरीब सेटिंग्स भी हैं, उदाहरण के लिए, समूह चलाएं:
<test name="Default tests" verbose="1" annotations="JDK" thread-count="10" parallel="classes"> <groups> <run> <exclude name="integration"/> </run> </groups> </test>
इस उदाहरण में, परीक्षण में केवल परीक्षण शामिल होंगे जो एकीकरण समूह का हिस्सा नहीं हैं।
अभी भी परीक्षणों में परीक्षण कक्षाएं शामिल हो सकती हैं, जो बदले में परीक्षण विधियों को शामिल / बहिष्कृत कर सकती हैं।
<test name="Integration tests"> <groups> <run> <include name="integration"/> </run> </groups> <classes> <class name="com.example.PrioritiesTest"> <methods> <exclude name="third"/> </methods> </class> </classes> </test>
निष्कर्ष
यह वह सब नहीं है जो इस अद्भुत ढांचे के लिए कहा जा सकता है, एक लेख में सब कुछ कवर करना बहुत मुश्किल है। लेकिन मैंने इसके उपयोग के मुख्य बिंदुओं को प्रकट करने का प्रयास किया। यहाँ, निश्चित रूप से, श्रोता तंत्र के बारे में कुछ और बता सकता है, अन्य रूपरेखाओं के साथ एकीकरण, परीक्षणों के विन्यास के बारे में, लेकिन फिर लेख एक किताब में बदल जाएगा, और मुझे सब कुछ पता नहीं है। लेकिन मुझे उम्मीद है कि यह लेख किसी के लिए उपयोगी था और जो कुछ कहा गया है वह कुछ पाठकों को टेस्टएनजी का उपयोग करने के लिए प्रोत्साहित करेगा, या कम से कम डीडीटी तकनीक को परीक्षण लिखने के लिए प्रोत्साहित करेगा।
उदाहरण
यहां , विभिन्न लेख
यहां देखे जा सकते
हैं ।
साहित्य