Тестирование Magento с использованием Selenium
-
Upload
magecom-ukraine -
Category
Technology
-
view
3.188 -
download
8
description
Transcript of Тестирование Magento с использованием Selenium
Testing Magento with Selenium IDE
Dmitriy Romanov
Professional Service QA Engineer
Contents Why Automate Testing ?
Why Selenium ?
“Create Simple Product with Related” Example :
Recording macro
Analyzing and fixing script source
Featuring script
Selenium Best Practices for Magento:
Using meaningful locators Using *waitfor for dynamical changes
Script parameterization with Variables Break out link between TestLogic and
XPath functions and expressions in Selenium How to add Assert* and Verify*
Working with Non-Visible Page Elements Using Comments
Why Automate Testing ?
Fast Execution and Feedback
Reliable
Repeatable
Comprehensive
Reusable parts
Better Software Quality
Overall QA Cost Reduction
Selenium usage example
Why Selenium ?
Why Selenium ?
Why Selenium ? Selenium IDE
• Begin: write and run tests in Firefox.
• Selenium IDE is a Firefox add-on that records clicks, typing, and other actions to make a test, which you can play back in the browser.
Selenium Remote Control (RC)
• Customize: your language, your browser.
• l (RC) runs your tests in multiple browsers and platforms. Tweak your tests in your preferred language.
Selenium Grid
• Deploy: scale out, speed up.
• Selenium Grid extends Selenium RC to distribute your tests across multiple servers, saving you time by running tests in parallel.
Selenium Advantages
Run directly in Browser
Support AJAX testing
Multibrowser
Multiplatform
Extendable
Multilanguage
Free and Open Source
Input Parameters:
Product Name: Simple Product
SKU sp-01
Price 12
WebSite Selenium
Category SeL
Related products SKU1 ssp-RA
Related products SKU2 ssp-RB
Condition to check:
Successful message: “Product was successfully saved.”
Для примера построения такого теста возьмем такую
часть функционала Админ части, как создание
простого (Simple) продукта.
В тесте заполним все необходимые поля для
отображения на фронте. Из необязательных –
добавим два related продукта.
Демонстрационное видео создания продукта
можно посмотреть отдельно.
click //ul[@id='nav']/li[3]/ul/li[1]/a/span
…
Finding solid start point:
Using meaningful locators:
click //ul[@id='nav']/li[3]/ul/li[1]/a/span
click //div[@class="nav-bar"]//li [a/span="Manage Products"]/a
Avoid autogenerated IDs:
click id_8ad1a1cebaeae9432f842806bb7bf99a
сlick id_481d270db32669b7f9f7092eedc00242
clickAndWait //button[span="Add Product"]
clickAndWait //button[span="Continue"]
Script parameterization with Variables
Recorded script:
select product_type label=Simple
Product
click id_481d270db32669
b7f9f7092eedc00242
type name Simple Product
type description Simple Product
type short_description Simple Product
type sku ssp-01
type weight 10
select status label=Enabled
Script parameterization with Variables
Introducing variables:
store Simple Product Name
store ssp-01 SKU
store Selenium Website
store SeL Category
store ssp-RA RelProdSKU1
store ssp-RB RelProdSKU2
Script parameterization with Variables
Using variables:
type name ${Name}
type description ${Name}
type short_description ${Name}
type sku ${SKU }
type weight 10
select status label=Enabled
Improve script readability
click //a[@id='product_info_tabs_group_5']/span
type Price 12
select tax_class_id label=Taxable Goods
click //a[@id='product_info_tabs_inventory']/span
type inventory_qty 1000
select inventory_stock_availability label=In Stock
click //ul[@id='product_info_tabs']//a[span='Prices']
type Price 12
select tax_class_id label=Taxable Goods
click //ul[@id='product_info_tabs']//a[span='Inventory']
type inventory_qty 1000
select inventory_stock_availability label=In Stock
Using XPath functions:
Website selection:
click //a[@id='product_info_tabs_websites']/span
click product_website_44
Updated version:
click //ul[@id='product_info_tabs']//a[span='Websites’]
click ???
Using XPath functions:
… div[@id='grop_fields']/div[12]/div[1]/big/strong/label
Using XPath functions:
//div[@id=’product_info_tabs_websites_content’]//label
//div[@id='product_info_tabs_websites_content'] //label[text()='Selenium Website']
label[text()=${Website}+' Website']
//div[@id='product_info_tabs_websites_content'] //label[text()=concat(${Website},' Website')]
//div[@id='product_info_tabs_websites_content'] //label[contains(text(),${Website})]
<label for="product_website_44" class=" ">Selenium Website</label>
Using XPath functions:
Using XPath functions:
Website selection:
click product_website_44
Updated version:
click //div[@id='product_info_tabs_websites_content']
//label[contains(text(),${Website})]
Working with AJAX:
Category selection:
click //a[@id='product_info_tabs_categories']/span
click ext-gen485
Updated version:
click //a[@id='product_info_tabs_categories']/span
click //div[@id='product-categories']
//a[contains(span,${Category})]
Причина в том, что сразу после перехода на закладку
категорий дерево категорий еще не отрисовано и нет
еще элемента с именем нашей категории.
Замена click на clickandwait здесь не поможет, т.к.,
фактически, страница не перегружается, а заново
отрисовывается только ее часть. Так работает AJAX-
технология, которая с помощью AJAX запросов/ответов
меняет содержимое страницы без полной перезагрузки.
Для того, чтобы найти решение, нужно ответить на
вопрос:
Что поменялось на странице ?
Working with AJAX:
Working with AJAX. Main Question
What’s up, Doc ?
Working with AJAX:
Awaiting AJAX Response Solutions:
Use Pause(waitTime)
OR
Get Answer for the Question:
“What’s changed on Page ?”
Working with AJAX:
Working with AJAX:
Working with AJAX:
Working with AJAX:
Category selection:
click //a[@id='product_info_tabs_categories']/span
click ext-gen485
click //a[@id='product_info_tabs_categories']/span
waitForElementNotPre
sent //div[@id='loading-mask' and contains(@style,'display: none')]
waitForElemenPresent //div[@id='loading-mask' and contains(@style,'display: none')]
Click //div[@id='product-categories']//a[contains(span,${Category})]
Dynamical changes:
Related products additions:
click //a[@id='product_info_tabs_related']/span
type filter_sku ssp-RA
click id_39e3a2128d47dfd177243389483acede
click //input[@name='' and @value='240']
type filter_sku ssp-RB
click id_39e3a2128d47dfd177243389483acede
click //input[@name='' and @value='241']
Dynamical changes: Corrected version:
click //ul[@id='product_info_tabs']//a[span='Related Products']
type filter_sku ${RelProdSK
U1}
click //*[@id='related_product_grid']//button[contains(span,'Search')]
waitForEleme
ntNotPresent //div[@id='loading-mask' and contains(@style,'display: none')]
waitForEleme
nPresent //div[@id='loading-mask' and contains(@style,'display: none')]
waitForEleme
ntPresent
//table[@id='related_product_grid_table']//td[contains(text(),${Rel
ProdSKU1})]
click //table[@id='related_product_grid_table']//td[contains(text(),${Rel
ProdSKU1})]
type filter_sku ${RelProdSK
U2}
click //*[@id='related_product_grid']//button[contains(span,'Search')]
waitForEleme
ntPresent
//table[@id='related_product_grid_table']//td[contains(text(),${Rel
ProdSKU1})]
сlick //table[@id='related_product_grid_table']//td[contains(text(),${Rel
ProdSKU1})]
Using User Interface Map
Original Selenese:
click id_1b1bca379a27ffade3083654c82ac9d9
Magento EE 1.6.x - 1.7.x:
ClickAndWait //button[span='Save And Continue Edit']
Magento EE 1.8.x:
ClickAndWait //button[span='Save and Continue Edit']
Using User Interface Map:
Dealing With Changed Design:
//button[contains(span,'Save’) and contains(span,'Edit’)']
OR
//button[upper-case(span)='SAVE AND CONTINUE EDIT']
OR
//button[translate(span,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKL
MNOPQRSTUVWXYZ')='SAVE AND CONTINUE EDIT']
OR
Using UI-Map
Using User Interface Map:
UI-Map Example for 1.6.x and 1.7.x :
var uiMap = new UIMap();
uiMap.addPageset({
name: 'Dashboard',
description: 'Main page with operations menu',
paths: ['index.php/control/index']
});
uiMap.addElement('Dashboard', {
name: 'saveandcontinue_button',
description: 'Save and Continue button',
locator: "xpath=//button[span='Save And Continue
Edit']"
});
Using UI-Map
UI-Map Example for 1.8.x :
...
locator: "xpath=//button[span='Save And Continue
Edit']"
...
Adding UI-Map extension to IDE:
Adding Assertion to Script:
assertTextPresent Product was successfully saved.
assertTextPresent Product has been successfully saved.
assertTextPresent ui=Dashboard::product_saved_message()
Review and Comment Source: 1 Input parameters
2 Store Simple Product Name
3 Store ssp-01 SKU
4 Store 'Selenium' Website
5 Store 'SeL-Category' Category
6 Store ssp-RA RelProdSKU1
7 Store ssp-RB RelProdSKU2
8 Open manage products, click "Add Product"
9 clickAndWait //div[@class="nav-bar"]//li[a/span="Manage
Products"]/a
10 clickAndWait //button[span="Add Product"]
11 clickAndWait //button[span="Continue"]
12 Fill General Tab
13 type name ${Name}
14 type description ${Name}
15 type short_description ${Name}
16 type sku ${SKU}
17 type weight 10
18 Select status label=Enabled
Review and Comment Source: 19 Fill Price Tab
20 click //ul[@id='product_info_tabs']//a[span='Prices']
21 type price 12
22 select tax_class_id label=Taxable Goods
23 Fill Inventory Tab
24 click //ul[@id='product_info_tabs']//a[span='Inventory']
25 type inventory_qty 100
26 select inventory_stock_availability label=In Stock
27 Fill Websites Tab
28 click //ul[@id='product_info_tabs']//a[span='Websites']
29 click //div[@id='product_info_tabs_websites_content']//label[contains(text(),$
{Website})]
30 Fill Category Tab
31 click //ul[@id='product_info_tabs']//a[span='Categories']
32 waitForElementNotPresent //div[@id='loading-mask' and contains(@style,'display: none')]
33 waitForElementPresent //div[@id='loading-mask' and contains(@style,'display: none')]
34 click //div[@id='product-categories']//a[contains(span,${Category})]
35 Fill Related Products Tab
36 click //ul[@id='product_info_tabs']//a[span='Related Products']
37 waitForElementPresent filter_sku
Review and Comment Source:
38 type filter_sku ${RelProdSKU1}
39 click //*[@id='related_product_grid']//button[contains(span,'Search')]
40 waitForElementNotPresent //div[@id='loading-mask' and contains(@style,'display: none')]
41 waitForElementPresent //div[@id='loading-mask' and contains(@style,'display: none')]
42 waitForElementPresent //table[@id='related_product_grid_table']//td[contains(text(),${RelProdSKU1
})]
43 click //table[@id='related_product_grid_table']//td[contains(text(),${RelProdSKU1
})]
44 type filter_sku ${RelProdSKU2}
45 click //*[@id='related_product_grid']//button[contains(span,'Search')]
46 waitForElementNotPresent //div[@id='loading-mask' and contains(@style,'display: none')]
47 waitForElementPresent //div[@id='loading-mask' and contains(@style,'display: none')]
48 waitForElementPresent //table[@id='related_product_grid_table']/tbody/tr/td[contains(text(),${RelPro
dSKU2})]
49 click //table[@id='related_product_grid_table']/tbody/tr/td[contains(text(),${RelPro
dSKU2})]
50 Save And Continue
51 click ui=Dashboard::saveandcontinue_button()
52 Product saved assertion
53 assertElementPresent ui=Dashboard::product_saved_message()
Script Changes Statistic and Conclusions:
Recorder Script Lines Count: 27 Final Script Lines Count: 56
Unchanged Lines: 7
Conclusions:
Selenium Best Practices for Magento:
Using meaningful locators Using *waitfor for dynamical changes
Script parameterization with Variables
Break out link between TestLogic and Design
Xpath and JavaScript functions and expressions in Selenium
When Assert* and Verify*
Working with Non-Visible Page Elements
Using Comments