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


92

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

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


Ext JS के अच्छे लोग इस तरह के विषय के बारे में यहाँ अपने ब्लॉग पर पोस्ट करने के लिए पर्याप्त हैं । आशा है कि ये आपकी मदद करेगा।
NBRed5

जवाबों:


173

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

सामान्य टिप्स

तत्वों का पता लगाना

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

एक सीएसएस या XPath लोकेटर के साथ एक आईडी लोकेटर की जगह

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

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

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

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 और धीरे प्रतिपादन के साथ परछती

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

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

क्षेत्र मान्यता

प्रपत्र फ़ील्ड (एक्सटफॉर्म। * घटक) जो सत्यापन के लिए नियमित अभिव्यक्ति या 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"))]

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

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

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

  • विकल्प 1

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

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

  • विकल्प 2

    कमांड: लक्ष्य पर क्लिक करें: css = # सेव-ऑप्शन बटन

    बटन को उसकी आईडी से चुनता है

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

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

पहले मान सेट करता है और फिर पर्यवेक्षकों के मामले में चयनित घटना को स्पष्ट रूप से आग लगाता है।


3
यहाँ कुछ मैनुअल सुझाव दिए गए हैं: rkapse.blogspot.nl/2009/06/selenium-ide-issues-with-extjs.html
dan-klasson

5

इस ब्लॉग ने मुझे बहुत मदद की। उन्होंने विषय पर काफी लिखा है और ऐसा लगता है कि यह अभी भी सक्रिय है। आदमी भी अच्छे डिजाइन की सराहना करने लगता है।

वह मूल रूप से प्रश्नों को करने के लिए जावास्क्रिप्ट भेजने का उपयोग करने के बारे में बात करता है और उसी तरह से सामान प्राप्त करने के लिए Ext.ComponentQuery.query विधि का उपयोग करता है जिस तरह से आप अपने एक्सट्रीम ऐप में आंतरिक रूप से करते हैं। इस तरह से आप xtypes और itemIds का उपयोग कर सकते हैं और न ही पागल ऑटो-जेनरेट किए गए किसी भी सामान को पार्स करने की कोशिश करने के बारे में चिंता करें।

मुझे यह लेख विशेष रूप से बहुत उपयोगी लगा।

जल्द ही यहाँ पर कुछ और अधिक विस्तृत पोस्ट कर सकते हैं - फिर भी यह ठीक से करने के लिए मेरे सिर के चारों ओर पाने की कोशिश कर रहा है


4

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

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

/**
 * 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) );

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


आप Ext.ComponentQuery.query में अपने xtype का उपयोग करके ग्रिड को खोजने में सक्षम होना चाहिए (यह मानते हुए कि आपने ग्रिड से विस्तार किया है और आपके लिए ग्रिड के लिए xtype को परिभाषित किया है) मैंने इसके बारे में कुछ और सामग्री नीचे रखी है। मैंने यह भी पाया कि आप td को खोजने के लिए xpath का उपयोग करके सामान पर क्लिक कर सकते हैं जिसमें एक पंक्ति के लिए एक पहचान मूल्य शामिल है
JonnyRaa

4

उस तत्व का पता लगाने के लिए आप क्लॉज का उपयोग करते हुए दिखाई देते हैं: not(contains(@style, "display: none")

इसका उपयोग करना बेहतर है:

visible_clause = "not(ancestor::*[contains(@style,'display: none')" +
    " or contains(@style, 'visibility: hidden') " + 
    " or contains(@class,'x-hide-display')])"

hidden_clause = "parent::*[contains(@style,'display: none')" + 
    " or contains(@style, 'visibility: hidden')" + 
    " or contains(@class,'x-hide-display')]"

3

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

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


3

Ext JS वेब पेज टेस्ट करने में मुश्किल हो सकते हैं, क्योंकि जटिल HTML के कारण वे Ext JS JS ग्रिड की तरह जनरेट करते हैं।

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

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

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

findExtJsGridRow("Foo");

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

extjsgridrow by text "Foo"

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


2

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

   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;
    }

2

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

से Sencha प्रलेखन :

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

अधिभावी Ext.AbstractComponentकी onBoxReadyविधि, मैं एक कस्टम डेटा विशेषता (जिसका नाम अपने कस्टम से आता सेट testIdAttrघटक के लिए प्रत्येक घटक की संपत्ति) itemId, मूल्य यदि वह मौजूद है। 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);
  }
});

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


2

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

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");
}

1

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

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

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

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

selenium.click(fullXpath);

1

जब मैं वेबड्राइवर का उपयोग करके एक्सटीजेएस एप्लिकेशन का परीक्षण कर रहा था, तो मैंने अगले दृष्टिकोण का उपयोग किया: मैंने लेबल के पाठ द्वारा फ़ील्ड की तलाश की और @forलेबल से विशेषता प्राप्त की। उदाहरण के लिए, हमारे पास एक लेबल है

<label id="dynamic_id_label" class="TextboxLabel" for="textField_which_I_am_lloking_for">
Name Of Needed Label
<label/>

और हमें कुछ इनपुट WebDriver को इंगित करने की आवश्यकता है //input[@id=(//label[contains(text(),'Name Of Needed Label')]/@for)]:।

तो, यह आईडी को @forविशेषता से चुन लेगा और इसे आगे उपयोग करेगा। यह शायद सबसे सरल मामला है लेकिन यह आपको तत्व का पता लगाने का रास्ता देता है। यह बहुत कठिन होता है जब आपके पास कोई लेबल नहीं होता है, लेकिन तब आपको कुछ तत्व खोजने की जरूरत होती है और अपने xpath को भाई-बहनों, उतरते / चढ़ते तत्वों की तलाश में लिखना होता है।

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