Автоматизация ui тестирования под windows и windows phone
TRANSCRIPT
Абалов Николай Головин Глеб
Автоматизация UI тестирования под Windows и Windows Phone
2
Ручные
GUI
API Интеграционные Компонентные
Модульные
3
Web
Icons by Edward Boatman,Kelig Le Luron,Roy Martens,Daniel,Martin Jordan,Yorlmar Campos,Kelig Le Luron from http://thenounproject.com/
3Icons by Edward Boatman,Kelig Le Luron,Roy Martens,Daniel,Martin Jordan,Yorlmar Campos,Kelig Le Luron from http://thenounproject.com/
State of the Union
4
forcedotcom/windowsphonedriver
5
5
5
6
TestStack/White
7
Selenium“free and open protocol for testing that has become a defacto standard”
Appium
Selenium 2.0 → 3.0
W3C working draft 2013
JsonWireProtocol
JsonWireProtocol over HTTP
WebDriver Implementation System under Test
Magic
8
HTTP/1.1 200 OK Content-‐Type: application/json;charset=UTF-‐8 Connection: close !
{"sessionId":"AwesomeSession", "status":0, "value":"CodeFest"}
GET http://127.0.0.1:9999/session/12345/element/2026335-‐1/text HTTP/1.1 ... Content-‐Type: application/json;charset=UTF-‐8 Connection: close Accept: application/json
Get element text (JSON Wire Example)
9
10
Open Source • Selenium • Awesome
Winium for Store Apps
11
12
JsonWireProtocol over HTTP
Xde API
Internal API over HTTP
XDE
Automation Server
Winium.StoreApps.Driver
Ваши тесты на Python, C#, JS,...
Тестируемое приложение
13
Быстрый старт
a. Готовим приложение
b. Пишем тесты
c. Поехали!
1. Добавляем NuGet пакет Winium.StoreApps.InnerServer
2. В MainPageOnLoaded создаем и запускаем сервер автоматизации
14
a. Подготовка приложения
#if DEBUG
AutomationServer.Instance.InitializeAndStart(Frame);
#endif // DEBUG
3. Обеспечиваем testability (прописываем идентификаторы и имена)
4. Собираем приложение и упаковываем его в appx
15
a. Подготовка приложения
Деплой и загрузка данных (python)dc = {'deviceName': 'Emulator 8.1 WVGA 4 inch 512MB', 'app': 'C:\\YorAppUnderTest.appx', 'files': { {'C:\\AppFiles\\file1.png': 'download\\file1.png', 'C:\\AppFiles\\file2.png': 'download\\file2.png'} }, 'debugConnectToRunningApp': False}
!
driver = Remote(command_executor=“http://localhost:9999”, desired_capabilities=dc)
16
Поиск элементов
17
id AutomationProperties.AutomationId
name AutomationProperties.Name
class name полное имя класса
tag name тоже, что и class name
xname x:Name
Winium Inspector
18
element = driver.find_element_by_id('MyTextBox') !
# получение значения текстового поляelement.text# 'Send me some keys' !
# кликнуть в элемент element.click() !
# ввести строкуelement.send_keys('Hello!'+Keys.ENTER)
Операции над элементами
19
Получение значений свойств# скаляры и строкиelement.get_attribute('Width')# 300 !
# вложенные свойства element.get_attribute('DesiredSize.Width')# 300 !
# прочие свойства, серилизуемые в JSONelement.get_attribute('DesiredSize')# '{"Width":300.0,"Height":114.0,"IsEmpty":false}'
20
# flick – “провести”, быстрое движение по экрануTouchActions(driver).flick_element(element, 0, 500, 100).perform()!
# scroll/swipe – “сдвинуть”, движение по экран без отрываTouchActions(driver).scroll(200,200).perform() !
# можно сделать свой жест ActionChains(driver) \.click_and_hold() \.move_by_offset(100, 100) \.release().perform()
Жесты
21
Дополнительные команд# использование invoke шаблонов app_bar_button = driver.find_element_by_id('GoAppBarButton')driver.execute_script('automation: invoke', app_bar_button)list_box = driver.find_element_by_id('MyListBox')si = {'v': 'smallIncrement', 'count': 10}driver.execute_script('automation: scroll', list_box, si) !
# задание значения свойства (скаляры и строки) text_box = driver.find_element_by_id('MyTextBox')driver.execute_script('attribute: set', text_box, 'Width', 10)driver.execute_script('attribute: set', text_box, 'Background.Opacity', 0.3)
22
https://github.com/2gis/Winium.StoreApps/wiki/Supported-Commands
NewSession !Close!Quit!GetPageSource!FindElement!FindElements!FindChildElement!FindChildElements!Screenshot!
ExecuteScript!ClickElement!GetElementText!GetElementAttribute!IsElementDisplayed!GetElementLocation!SendKeysToElement!GetWindowSize!GoBack
MouseMoveTo!MouseClick!MouseDown!MouseUp!TouchSingleTap!TouchScroll!TouchFlick!...!
23
Все команды
b. Пишем тестыimport unittestfrom selenium.webdriver import Remote!
class TestMainPage(unittest.TestCase): desired_capabilities = {"app": "C:\\YorAppUnderTest.appx"} def setUp(self): self.driver = Remote(command_executor="http://localhost:9999", desired_capabilities=self.desired_capabilities) def test_button_tap_should_set_textbox_content(self): self.driver.find_element_by_id('SetButton').click() assert 'CARAMBA' == self.driver.find_element_by_id('MyTextBox').text def tearDown(self): self.driver.quit() 24
c. Поехали!
1. Запускаем Winium.StoreApps.Driver.exe (релиз доступен на github)
2. Запускаем тесты и наслаждаемся магией
25
DemoWinium.StoreApps VS 2GIS app
26
27
27
Winium for Desktop& Cruciatus
29
30
Тестируемое приложение
Рабочий столWinium.CruciatusUI Automation
Framework
31
Почему Winium.Cruciatus?
1. Достаточно Professional версии Visual Studio
2. Любой тестовый фреймворк (например NUnit)
3. Легко использовать
Пример использования Winium.Cruciatus[Test] public void SetTextButtonTest() { var window = CruciatusFactory.Root.FindElementByUid("MainWindow"); var textBox = window.FindElementByUid("TextBox"); var setButton = window.FindElementByUid("SetTextButton"); !
textBox.SetText("NOT CARAMBA"); setButton.Click(); !
Assert.AreEqual(textBox.Text(), "CARAMBA"); }
32
DemoWinium.Cruciatus
33
34
34
What about driver?
36
Ваши тесты на Python, C#, JS,...
JsonWireProtocol over HTTP
37
Winium.Desktop. Driver Тестируемое
приложение
Рабочий столWinium.CruciatusUI Automation
Framework
https://github.com/2gis/Winium.Desktop/wiki/Supported-Commands 38
NewSession !Close!Quit!FindElement!FindElements!ClickElement!
Считаем на калькуляторе
39
План действий:
1. Запускаем калькулятор
2. Выбираем инженерный режим
3. Считаем "2^8"
4. Закрываем калькулятор
# запускаем калькулятор driver = Remote(command_executor='http://localhost:9999', desired_capabilities={'app': 'C:/windows/system32/calc.exe'}) window = driver.find_element_by_class_name('CalcFrame') # находим его окноview_menu_item = window.find_element_by_name('View') # и меню “Вид”
Считаем на калькуляторе (python)
40
# запускаем калькулятор driver = Remote(command_executor='http://localhost:9999', desired_capabilities={'app': 'C:/windows/system32/calc.exe'}) window = driver.find_element_by_class_name('CalcFrame') # находим его окноview_menu_item = window.find_element_by_name('View') # и меню “Вид” view_menu_item.click() # раскрываем менюview_menu_item.find_element_by_name('Scientific').click() # выбираем режим
Считаем на калькуляторе (python)
41
# запускаем калькулятор driver = Remote(command_executor='http://localhost:9999', desired_capabilities={'app': 'C:/windows/system32/calc.exe'}) window = driver.find_element_by_class_name('CalcFrame') # находим его окноview_menu_item = window.find_element_by_name('View') # и меню “Вид” view_menu_item.click() # раскрываем менюview_menu_item.find_element_by_name('Scientific').click() # выбираем режим window.find_element_by_id('132').click() # 2window.find_element_by_id('97').click() # ̂window.find_element_by_id('138').click() # 8window.find_element_by_id('121').click() # =
Считаем на калькуляторе (python)
42
# запускаем калькулятор driver = Remote(command_executor='http://localhost:9999', desired_capabilities={'app': 'C:/windows/system32/calc.exe'}) window = driver.find_element_by_class_name('CalcFrame') # находим его окноview_menu_item = window.find_element_by_name('View') # и меню “Вид” view_menu_item.click() # раскрываем менюview_menu_item.find_element_by_name('Scientific').click() # выбираем режим window.find_element_by_id('132').click() # 2window.find_element_by_id('97').click() # ̂window.find_element_by_id('138').click() # 8window.find_element_by_id('121').click() # = driver.close() # закрываем калькулятор
Считаем на калькуляторе (python)
43
Считаем на калькуляторе (c#)var dc = new DesiredCapabilities();dc.SetCapability("app", @"C:/windows/system32/calc.exe");var driver = new RemoteWebDriver(new Uri("http://localhost:9999"), dc);var window = driver.FindElementByClassName("CalcFrame"); // находим его окноvar viewMenuItem = window.FindElement(By.Name("View")); // и меню “Вид”!viewMenuItem.Click(); // раскрываем менюviewMenuItem.FindElement(By.Name("Scientific")).Click(); // “Инженерный” режимwindow.FindElement(By.Id("132")).Click(); // 2window.FindElement(By.Id("97")).Click(); // ̂window.FindElement(By.Id("138")).Click(); // 8window.FindElement(By.Id("121")).Click(); // =driver.Close(); // закрываем калькулятор
44
DemoWinium.Desktop VS Calculator
45
46
46
Future
48
Спасибо
https://github.com/2gis/Winium
Головин Глеб [email protected]
Абалов Николай [email protected]
49