Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Тестирование Magento с использованием Selenium
1.
2. Testing Magento with
Selenium IDE
Dmitriy Romanov
Professional Service QA Engineer
dmitriy.romanov@varien.com
3. 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
4. Why Automate Testing ?
Fast Execution and Feedback
Reliable
Repeatable
Comprehensive
Reusable parts
Better Software Quality
Overall QA Cost Reduction
8. 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.
9.
10. Selenium Advantages
Run directly in Browser
Support AJAX testing
Multibrowser
Multiplatform
Extendable
Multilanguage
Free and Open Source
11. 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.”
12. Для примера построения такого теста возьмем такую
часть функционала Админ части, как создание
простого (Simple) продукта.
В тесте заполним все необходимые поля для
отображения на фронте. Из необязательных –
добавим два related продукта.
Демонстрационное видео создания продукта
можно посмотреть отдельно.
17. Script parameterization with Variables
Recorded script:
label=Simple
select product_type
Product
id_481d270db32669
click
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
18. 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
19. 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
20. 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
26. 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
//div[@id='product-categories']
click
//a[contains(span,${Category})]
27. Причина в том, что сразу после перехода на закладку
категорий дерево категорий еще не отрисовано и нет
еще элемента с именем нашей категории.
Замена click на clickandwait здесь не поможет, т.к.,
фактически, страница не перегружается, а заново
отрисовывается только ее часть. Так работает AJAX-
технология, которая с помощью AJAX запросов/ответов
меняет содержимое страницы без полной перезагрузки.
Для того, чтобы найти решение, нужно ответить на
вопрос:
Что поменялось на странице ?
34. 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})]
35. 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']
37. 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']
38. 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
39. 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']"
});
42. Adding Assertion to Script:
assertTextPresent Product was successfully saved.
assertTextPresent Product has been successfully saved.
assertTextPresent ui=Dashboard::product_saved_message()
43. 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"
//div[@class="nav-bar"]//li[a/span="Manage
9 clickAndWait
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
44. 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']
//div[@id='product_info_tabs_websites_content']//label[contains(text(),$
29 click
{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
45. 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')]
//table[@id='related_product_grid_table']//td[contains(text(),${RelProdSKU1
42 waitForElementPresent
})]
//table[@id='related_product_grid_table']//td[contains(text(),${RelProdSKU1
43 click
})]
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')]
//table[@id='related_product_grid_table']/tbody/tr/td[contains(text(),${RelPro
48 waitForElementPresent
dSKU2})]
//table[@id='related_product_grid_table']/tbody/tr/td[contains(text(),${RelPro
49 click
dSKU2})]
50 Save And Continue
51 click ui=Dashboard::saveandcontinue_button()
52 Product saved assertion
53 assertElementPresent ui=Dashboard::product_saved_message()
46. Script Changes Statistic and Conclusions:
Recorder Script Lines Count:
27
Final Script Lines Count:
56
Unchanged Lines: 7
47. Conclusions:
Selenium Best Practices for Magento:
Using *waitfor for dynamical
Using meaningful locators
changes
Script parameterization with Break out link between
Variables TestLogic and Design
Xpath and JavaScript functions
When Assert* and Verify*
and expressions in Selenium
Working with Non-Visible Page
Using Comments
Elements