unit testing - ब्राउज़र में extjs कोड का परीक्षण करने के लिए कोई सुझाव, अधिमानतः सेलेनियम के साथ?




unit-testing selenium (8)

कस्टम एचटीएमएल डेटा- विशेषताओं के माध्यम से आसान परीक्षण

सेन्चा दस्तावेज से :

कोई वस्तु संदर्भ किसी घटक के संदर्भ प्राप्त करने के वैकल्पिक विकल्प के रूप में उपयोग नहीं किया जा सकता है जब कोई ऑब्जेक्ट संदर्भ उपलब्ध नहीं होता है। Ext.getCmp के साथ एक आईडी का उपयोग करने के बजाय, आइटम आईडी का उपयोग Ext.container.Container.getComponent के साथ करें जो आइटम आईडी या आईडी को पुनर्प्राप्त करेगा। चूंकि itemId कंटेनर के आंतरिक मिश्रित कोलेक्शन के लिए एक सूचकांक है, तो आइटम आईडी को कंटेनर में स्थानीय रूप से स्कॉप्ड किया जाता है - Ext.ComponentManager के साथ संभावित विवादों से परहेज करना जिसके लिए एक अद्वितीय आईडी की आवश्यकता होती है।

Ext.AbstractComponent की onBoxReady , मैं एक कस्टम डेटा विशेषता (जिसका नाम प्रत्येक घटक की मेरी कस्टम testIdAttr प्रॉपर्टी से आता है) घटक के testIdAttr मान पर, यदि यह मौजूद है। Testing.overrides.AbstractComponent क्लास को अपने application.js फ़ाइल में जोड़ें सरणी की requires

/**
 * Overrides the Ext.AbstracComponent's onBoxReady
 * method to add custom data attributes to the
 * component's dom structure.
 *
 * @author Brian Wendt
 */
Ext.define('Testing.overrides.AbstractComponent', {
  override: 'Ext.AbstractComponent',


  onBoxReady: function () {
    var me = this,
      el = me.getEl();


    if (el && el.dom && me.itemId) {
      el.dom.setAttribute(me.testIdAttr || 'data-selenium-id', me.itemId);
    }


    me.callOverridden(arguments);
  }
});

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

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

क्या किसी ने एक्स्टजेस-आधारित वेब पेजों के लिए स्वचालित परीक्षण लिखने में सफलता प्राप्त की है? बहुत सारे गुगलिंग समान समस्याओं वाले लोगों को पाता है, लेकिन कुछ जवाब। धन्यवाद!


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

एचटीएमएल 5 रोबोट गुणों और शर्तों के आधार पर घटकों के साथ विश्वसनीय रूप से लुकअप और बातचीत करने के लिए सर्वोत्तम प्रथाओं की एक श्रृंखला का उपयोग करके इसके साथ सौदा करता है जो गतिशील नहीं हैं। इसके बाद यह सभी एचटीएमएल, एक्सटी जेएस और सेन्चा टच घटकों के साथ ऐसा करने के लिए शॉर्टकट प्रदान करता है जिन्हें आपको बातचीत करने की आवश्यकता होगी। यह 2 स्वादों में आता है:

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

उदाहरण के लिए यदि आप "फू" टेक्स्ट वाले एक्सटी जेएस ग्रिड पंक्ति को ढूंढना चाहते हैं, तो आप जावा में निम्न कार्य कर सकते हैं:

findExtJsGridRow("Foo");

... और आप ग्वेन में निम्नलिखित कर सकते हैं:

extjsgridrow by text "Foo"

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


क्या आप extjs परीक्षण के साथ होने वाली समस्याओं के प्रकारों में अधिक अंतर्दृष्टि प्रदान कर सकते हैं?

एक सेलेनियम एक्सटेंशन मुझे उपयोगी लगता है waitForCondition । अगर आपकी समस्या अजाक्स घटनाओं में परेशानी प्रतीत होती है, तो आप घटनाओं के इंतजार के लिए प्रतीक्षा करने के लिए प्रतीक्षा करें।


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

आप किसी निश्चित तत्व के xpath का परीक्षण करने के लिए फ़ायरफ़ॉक्स एक्सटेंशन के रूप में फ़ायरफ़ॉक्स और फ़ायरक्सपाथ का उपयोग कर सकते हैं, और सेलेनियम के पैरामीटर के रूप में पूर्ण xpath को सरल पास कर सकते हैं।

उदाहरण के लिए जावा कोड में:

String fullXpath = "xpath=//div[@id='mainDiv']//div[contains(@class,'x-grid-row')]//table/tbody/tr[1]/td[1]//button"

selenium.click(fullXpath);

पेज पर ग्रिड के आईडी के माध्यम से ग्रिड लाने के लिए उपयोगी टिप्स: मुझे लगता है कि आप इस एपीआई से अधिक उपयोगी फ़ंक्शन का विस्तार कर सकते हैं।

   sub get_grid_row {
        my ($browser, $grid, $row)  = @_;


        my $script = "var doc = this.browserbot.getCurrentWindow().document;\n" .
            "var grid = doc.getElementById('$grid');\n" .
            "var table = grid.getElementsByTagName('table');\n" .
            "var result = '';\n" .
            "var row = 0;\n" . 
            "for (var i = 0; i < table.length; i++) {\n" .
            "   if (table[i].className == 'x-grid3-row-table') {\n".
            "       row++;\n" . 
            "       if (row == $row) {\n" .
            "           var cols_len = table[i].rows[0].cells.length;\n" .
            "           for (var j = 0; j < cols_len; j++) {\n" .
            "               var cell = table[i].rows[0].cells[j];\n" .
            "               if (result.length == 0) {\n" .
            "                   result = getText(cell);\n" .
            "               } else { \n" .
            "                   result += '|' + getText(cell);\n" .
            "               }\n" .
            "           }\n" .
            "       }\n" .
            "   }\n" .
            "}\n" .
            "result;\n";

        my $result = $browser->get_eval($script);
        my @res = split('\|', $result);
        return @res;
    }

मैं सेलेनियम के साथ अपने ExtJs वेब अनुप्रयोग का परीक्षण कर रहा हूं। सबसे बड़ी समस्या में से एक ग्रिड में एक आइटम का चयन करने के लिए कुछ करने के लिए चयन कर रहा था।

इसके लिए, मैंने सहायक विधि लिखी (SeleniumExtJsUtils कक्षा में जो ExtJs के साथ आसान बातचीत के लिए उपयोगी विधियों का संग्रह है):

/**
 * Javascript needed to execute in order to select row in the grid
 * 
 * @param gridId Grid id
 * @param rowIndex Index of the row to select
 * @return Javascript to select row
 */
public static String selectGridRow(String gridId, int rowIndex) {
    return "Ext.getCmp('" + gridId + "').getSelectionModel().selectRow(" + rowIndex + ", true)";
}

और जब मुझे एक पंक्ति चुनने की ज़रूरत होती, तो मैं बस फोन करता था:

selenium.runScript( SeleniumExtJsUtils.selectGridRow("<myGridId>", 5) );

इसके लिए काम करने के लिए मुझे अपनी आईडी को ग्रिड पर सेट करने की आवश्यकता है और एक्स्टजेज़ को स्वयं उत्पन्न नहीं होने दें।


सेलेनियम के साथ एक्स्टजेस का परीक्षण करने में सबसे बड़ी बाधा यह है कि एक्स्टजेस मानक एचटीएमएल तत्व प्रस्तुत नहीं करता है और सेलेनियम आईडीई नैतिक रूप से (और सही ढंग से) उन तत्वों पर लक्षित आदेश उत्पन्न करेगा जो सजावट के रूप में कार्य करते हैं - अनावश्यक तत्व जो पूरे डेस्कटॉप के साथ एक्स्टजेस की मदद करते हैं- देखो और महसूस। एटीजेएस ऐप के खिलाफ स्वचालित सेलेनियम परीक्षण लिखते समय मैंने कुछ सुझाव और युक्तियां एकत्र की हैं।

सामान्य युक्तियाँ

तत्व ढूंढना

फ़ायरफ़ॉक्स पर सेलेनियम आईडीई के साथ उपयोगकर्ता क्रियाओं को रिकॉर्ड करके सेलेनियम परीक्षण के मामलों को उत्पन्न करते समय, सेलेनियम HTML तत्वों के आईडी पर रिकॉर्ड किए गए कार्यों का आधार रखेगा। हालांकि, अधिकांश क्लिक करने योग्य तत्वों के लिए, ExtJS "ext-gen-345" जैसे उत्पन्न आईडी का उपयोग करता है, जो किसी भी पृष्ठ पर आने वाली विज़िट पर बदलने की संभावना है, भले ही कोई कोड परिवर्तन नहीं किया गया हो। परीक्षण के लिए उपयोगकर्ता क्रियाओं को रिकॉर्ड करने के बाद, जेनरेट की गई आईडी पर निर्भर करने और उन्हें बदलने के लिए ऐसे सभी कार्यों को पार करने के लिए मैन्युअल प्रयास होना आवश्यक है। दो प्रकार के प्रतिस्थापन किए जा सकते हैं जिन्हें बनाया जा सकता है:

एक सीएसएस या XPath लोकेटर के साथ एक आईडी लोकेटर को बदलना

सीएसएस locators "css =" से शुरू होते हैं और XPath locators "//" से शुरू होते हैं ("xpath =" उपसर्ग वैकल्पिक है)। सीएसएस लोकेटर कम वर्बोज़ हैं और पढ़ने के लिए आसान हैं और XPath locators पर प्राथमिकता दी जानी चाहिए। हालांकि, ऐसे मामले हो सकते हैं जहां XPath locators का उपयोग करने की आवश्यकता है क्योंकि एक सीएसएस लोकेटर बस इसे काट नहीं सकता है।

जावास्क्रिप्ट निष्पादित करना

ExtJS द्वारा किए गए जटिल प्रतिपादन के कारण कुछ तत्वों को सरल माउस / कीबोर्ड इंटरैक्शन से अधिक की आवश्यकता होती है। उदाहरण के लिए, एक Ext.form.CombBox वास्तव में एक <select> तत्व नहीं है लेकिन एक अलग ड्रॉप-डाउन सूची वाला टेक्स्ट इनपुट जो दस्तावेज़ पेड़ के नीचे कहीं भी है। कॉम्बोबॉक्स चयन को सही तरीके से अनुकरण करने के लिए, पहले ड्रॉप-डाउन तीर पर क्लिक को अनुकरण करना और फिर दिखाई देने वाली सूची पर क्लिक करना संभव है। हालांकि, इन तत्वों को सीएसएस या एक्सपीएथ लोकेटर के माध्यम से ढूंढना बोझिल हो सकता है। चयन का अनुकरण करने के लिए कॉमबॉक्स घटक स्वयं का पता लगाने और उस पर कॉल करने के तरीकों का एक विकल्प है:

var combo = Ext.getCmp('genderComboBox'); // returns the ComboBox components
combo.setValue('female'); // set the value
combo.fireEvent('select'); // because setValue() doesn't trigger the event

सेलेनियम में उपरोक्त ऑपरेशन को अधिक संक्षिप्त रूप में करने के लिए runScript कमांड का उपयोग किया जा सकता है:

with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }

AJAX और धीमी रेंडरिंग के साथ मुकाबला

सेलेनियम में पृष्ठ लोड के इंतजार के लिए सभी आदेशों के लिए "* AndWait" स्वाद होता है जब उपयोगकर्ता क्रिया पृष्ठ परिवर्तन या पुनः लोड में परिणाम देती है। हालांकि, चूंकि AJAX fetches में वास्तविक पृष्ठ लोड शामिल नहीं हैं, इसलिए इन आदेशों का उपयोग सिंक्रनाइज़ेशन के लिए नहीं किया जा सकता है। समाधान एजेक्स प्रगति संकेतक की उपस्थिति / अनुपस्थिति या ग्रिड, अतिरिक्त घटकों, लिंक इत्यादि में पंक्तियों की उपस्थिति जैसे दृश्य सुरागों का उपयोग करना है उदाहरण के लिए:

Command: waitForElementNotPresent
Target: css=div:contains('Loading...')

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

Command: waitForElementPresent
Target: css=span:contains('Do the funky thing')
Command: click
Target: css=span:contains('Do the funky thing')

मनमाने ढंग से विरामों पर निर्भर करना एक अच्छा विचार नहीं है क्योंकि अलग-अलग ब्राउज़रों या विभिन्न मशीनों पर परीक्षण चलाने से होने वाले समय के मतभेद परीक्षण मामलों को कमजोर कर देंगे।

गैर-क्लिक करने योग्य आइटम

click कमांड द्वारा कुछ तत्व ट्रिगर नहीं किए जा सकते हैं। ऐसा इसलिए है क्योंकि घटना श्रोता वास्तव में कंटेनर पर है, अपने बच्चों के तत्वों पर माउस घटनाओं के लिए देख रहा है, जो अंततः माता-पिता को बुलबुला करता है। टैब नियंत्रण एक उदाहरण है। किसी टैब पर क्लिक करने के लिए, आपको टैब लेबल पर mouseDown ईवेंट अनुकरण करना होगा:

Command: mouseDownAt
Target: css=.x-tab-strip-text:contains('Options')
Value: 0,0

फील्ड सत्यापन

प्रपत्र फ़ील्ड्स (Ext.form। * घटक) जो सत्यापन के लिए नियमित अभिव्यक्तियों या vtypes से जुड़े हैं, एक निश्चित विलंब के साथ सत्यापन को ट्रिगर करेंगे ( validationDelay को हटाएं, जो डिफ़ॉल्ट रूप से 250ms पर सेट है), जब उपयोगकर्ता टेक्स्ट दर्ज करता है या तुरंत क्षेत्र में प्रवेश करता है फोकस खो देता है - या ब्लर्स ( validateOnDelay संपत्ति देखें)। किसी क्षेत्र के अंदर कुछ पाठ दर्ज करने के लिए सेलेनियम कमांड को जारी करने के बाद फ़ील्ड सत्यापन को ट्रिगर करने के लिए, आपको निम्न में से कोई एक करना होगा:

  • विलंबित सत्यापन को ट्रिगर करना

    फ़ील्ड कुंजीपटल घटनाओं को प्राप्त करते समय एक्स्टजेस सत्यापन विलंब टाइमर को निकाल देता है। इस टाइमर को ट्रिगर करने के लिए, बस एक डमी कीप इवेंट जारी करें (इससे कोई फ़र्क नहीं पड़ता कि आप जिस कुंजी को एक्सटीजेएस के रूप में उपयोग करते हैं, उसे अनदेखा करता है), उसके बाद एक छोटा विराम होता है जो सत्यापन से अधिक लंबा होता है:

    Command: keyUp
    Target: someTextArea
    Value: x
    Command: pause
    Target: 500
    
  • तत्काल सत्यापन ट्रिगरिंग

    तत्काल सत्यापन को ट्रिगर करने के लिए आप क्षेत्र में धुंधला ईवेंट इंजेक्ट कर सकते हैं:

    Command: runScript
    Target: someComponent.nameTextField.fireEvent("blur")
    

प्रमाणीकरण परिणामों की जांच

सत्यापन के बाद, आप किसी त्रुटि फ़ील्ड की उपस्थिति या अनुपस्थिति की जांच कर सकते हैं:

Command: verifyElementNotPresent   
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]

Command: verifyElementPresent   
Target: //*[@id="nameTextField"]/../*[@class="x-form-invalid-msg" and not(contains(@style, "display: none"))]

ध्यान दें कि "डिस्प्ले: कोई नहीं" चेक आवश्यक है क्योंकि एक बार त्रुटि फ़ील्ड दिखाया जाता है और फिर इसे छुपाया जाना चाहिए, ExtJS पूरी तरह से इसे DOM पेड़ से हटाने के बजाय त्रुटि फ़ील्ड को छुपाएगा।

तत्व-विशिष्ट युक्तियाँ

Ext.form.Button पर क्लिक करना

  • विकल्प 1

    कमांड: लक्ष्य पर क्लिक करें: css = बटन: इसमें शामिल है ('सहेजें')

    अपने कैप्शन द्वारा बटन का चयन करता है

  • विकल्प 2

    कमांड: लक्ष्य पर क्लिक करें: css = # save-options बटन

    अपने आईडी द्वारा बटन का चयन करता है

Ext.form.ComboBox से एक मान का चयन करना

Command: runScript
Target: with (Ext.getCmp('genderComboBox')) { setValue('female'); fireEvent('select'); }

सबसे पहले मान सेट करता है और फिर पर्यवेक्षकों के मामले में स्पष्ट ईवेंट को स्पष्ट रूप से निकाल देता है।


हम एक परीक्षण ढांचा विकसित कर रहे हैं जो सेलेनियम का उपयोग करता है और extjs के साथ समस्याओं का सामना करना पड़ता है (क्योंकि यह क्लाइंट साइड प्रतिपादन है)। एक बार डोम तैयार होने के बाद मुझे तत्व की तलाश करना उपयोगी लगता है।

public static boolean waitUntilDOMIsReady(WebDriver driver) {
    def maxSeconds = DEFAULT_WAIT_SECONDS * 10
    for (count in 1..maxSeconds) {
        Thread.sleep(100)
        def ready = isDOMReady(driver);
        if (ready) {
            break;
        }
    }
}

public static boolean isDOMReady(WebDriver driver){
    return driver.executeScript("return document.readyState");
}




web-testing