In this talk I present free open-source tool for Windows Phone and Desktop test automation called Winium.
Winium is Selenium WebDriver implementation for native Windows Phone and Desktop apps.
The talk is divided in 3 major parts:
1. Windows Phone automation using Winium.StoreApps and Winium CodedUI with Demos.
2. Windows Desktop automation using Winium.Desktop with Demo
3. Cross platfrom automation using Appium + Winium with Demo.
https://www.youtube.com/playlist?list=PLr-vbeTuGcNbIT5DpG1vgnvG1PeK0hr2-
2. Who am I?
2
Nikolai Abalov
Software Development Engineer in Test at 2GIS
@nickab NickAb
3. Outline
3
• Background & motivation
• What is Selenium, JsonWire Protocol & Appium
• Windows Phone Automation
• Existing tools
• Winium – Selenium for Windows
• How it works
• Quick start
• Milestones
• Windows Desktop Automation
• Existing tools
• Winium – Selenium for Windows
• How it works
• Quick start
• Cross Platform Automation
6. 6
• Selenium 2.0 → 3.0
• W3C working draft
• JsonWireProtocol
JsonWireProtocol
Over HTTP
WebDriver
Implementation
System
under test
Magic
7. Get element text (JSON Wire Example)
7
GET
http://127.0.0.1:9999/session/AwesomeSession/element/2026335-‐1/text
HTTP/1.1
...
Content-‐Type:
application/json;charset=UTF-‐8
Connection:
close
Accept:
application/json
HTTP/1.1
200
OK
Content-‐Type:
application/json;charset=UTF-‐8
Connection:
close
{"sessionId":"AwesomeSession",
"status":0,
"value":"CodeFest"}
9. Why we love Selenium & Appium?
9
• Free and open-source
• Cross platform
• Great community
• Simple and easy to use protocol
• Client binding for all major programming languages
12. 12
October 2010 Windows Phone 7
October 2011 Expensify • WindowsPhoneTestFramework (BDD, Native Apps)
October 2012 Windows Phone 8
March 2014 WinphoneDriver (Selenium, Native Apps, Silverlight, WP 8.0)
April 2014 Windows Phone 8.1 • MS Coded UI (Native Apps, Visual Studio Premium or higher)
May 2014 Forcedotcom • WinphoneDriver (Selenium, Web Apps)
June 2014 WinphoneDriver (updated for WP 8.1)
February 2015 Winium.StoreApps (Selenium, Native Apps, WP 8.1, Store Apps)
April 2015 Winium.StoreApps.CodedUi (Selenium, Native, Hybrid*, WP 8.1, Store Apps, Silverlight)
15. Features
15
• The only mobile WebDriver implementation that supports Native
Windows Phone apps
• Compatible with JSON Wire Protocol
• UI elements can be found by different locator types
• File deployment
• Gestures are supported (single touch)
• Inspector
16. Limitations
16
• Emulators only (no device support)
• Requires InnerServer to be embedded into the app under test*
• One session at a time**
19. Prepare the app
19
1. Add NuGet package Winium.StoreApps.InnerServer
2. In MainPageOnLoaded (or anywhere on UI thread) initialize and
start server
#if
DEBUG
AutomationServer.Instance.InitializeAndStart();
#endif
//
DEBUG
3. Make your app testable (assign automation names, ids, etc.)
4. Build and package your appx
20. Write tests
20
Use Selenium or Appium bindings and write tests just like you
would for web or iOS and Android
24. Acting on elements
24
element
=
driver.find_element_by_id('MyTextBox')
#
get
text
value
element.text
#
>>
'Send
me
some
keys'
element.click()
#
send
keys
to
the
element
element.send_keys('Hello!'+Keys.ENTER)
25. Get value of any public property of element
25
#
scalars
and
strings
element.get_attribute('Width')
#
300
#
nested
properties
element.get_attribute('DesiredSize.Width')
#
300
#
other
properties,
serialized
as
JSON
element.get_attribute('DesiredSize')
#
'{"Width":300.0,"Height":114.0,"IsEmpty":false}'
26. Touch
26
TouchActions(driver).flick_element(element,
0,
500,
100).perform()
TouchActions(driver).scroll(200,200).perform()
#
create
your
own
touch
gesture
ActionChains(driver)
.click_and_hold()
.move_by_offset(100,
100)
.release().perform()
#
We
implement
JSONWire
Protocol
actions
API
#
Support
for
new
Mobile
WebDriver
API
will
be
added
soon
27. Extended commands
27
#
direct
use
of
Windows
Phone
automation
APIs
app_bar_button
=
driver.find_element_by_id('GoAppBarButton')
driver.execute_script('automation:
InvokePattern.Invoke',
app_bar_button)
list_box
=
driver.find_element_by_id('MyListBox')
si
=
{'v':
'smallIncrement',
'count':
10}
driver.execute_script('automation:
ScrollPattern.Scroll',
list_box,
si)
#
setting
value
of
public
property
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)
32. Milestones
32
• Multiple sessions support
• Windows 10 support
• Refactor InnerServer and Driver communication
• GPS, Network and Sensors simulation
• Web and Hybrid apps supports
• Multi-touch gestures
35. Features
35
• No modification of app under test required to automate it
(Appium Rule 1)
• Runs on both Emulators and Devices
• Compatible with JSON Wire Protocol
• Already has limited support for Hybrid apps
42. Features
42
• Automate native Windows Desktop app (WinForms, WPF, every
app, that uses MS accessibility)
• Compatible with JSON Wire Protocol
• Full access to desktop and UI
• Protocol extensions for desktop specific elements
(Winium.Elements for C#)
43. Limitations
43
• Uses real mouse and keyboard events, i.e. you can’t run more
than one session on same machine, or use mouse while tests
are running
48. Automating calc.exe (C# bindings)
48
//
setup
var
dc
=
new
DesiredCapabilities();
dc.SetCapability("app",
@"C:/windows/system32/calc.exe");
var
driver
=
new
RemoteWebDriver(new
Uri("http://localhost:9999"),
dc);
//
test
var
window
=
driver.FindElementByClassName("CalcFrame");
var
menu
=
driver.FindElement(By.Id("MenuBar"));
var
viewMenuItem
=
menu.FindElement(By.Name("View"));
viewMenuItem.Click();
viewMenuItem.FindElement(By.Name("Scientific")).Click();
window.FindElement(By.Id("132")).Click();
//
2
window.FindElement(By.Id("97")).Click();
//
^
window.FindElement(By.Id("138")).Click();
//
8
window.FindElement(By.Id("121")).Click();
//
=
var
result
=
windows.FindElement(By.Id("150")).GetAttribute("Name");
Assert.AreEqual("256",
result);
//
teardown
driver.Close();
51. Introduction
51
• We have mobile app for 3 major platforms
• iOS
• Android
• Windows Phone
• We have similar interface for all platforms
• We have separate dev and qa teams for each platform
• We use Appium for iOS & Android, Winium for WP
• Each team writes common test cases and reinvents the wheel
52. 52
iOS Dev & QA Team Android Dev & QA Team WP Dev & QA Team
iOS4 UI tests
Appium
Android4 UI tests
Appium
WP4 UI tests
Winium
53. 53
iOS Dev & QA Team Android Dev & QA Team WP Dev & QA Team
Appium
v4 UI tests
Winium
54. What are benefits of common tests?
54
• No more wheel reinvention
• Less code duplicity, easier to maintain
• Better code quality and practices
• Knowledge sharing
• Systematic approach
• Faster test development
57. Platform specific implementation
57
#
coding:
utf-‐8
from
classes.android.components.component
import
Component
from
classes.android.helpers
import
get_android_text
from
classes.interfaces.components.search_bar
import
ISearchBar
class
SearchBar(Component,
ISearchBar):
def
open_search(self):
from
classes.android.pages.search_page
import
SearchPage
self.element.click()
return
SearchPage(self.driver)
def
text(self):
return
get_android_text(self.element)
def
is_displayed(self):
return
self.element.is_displayed()
58. Conditional entrypoint
58
from
config
import
config,
platform,
Platforms
#
In
languages
like
C#
or
Java
conditional
import
will
be
replaced
with
some
kind
of
factory
#
For
python
I
would
also
recommend
factory
pattern
instead
of
magic
imports
if
platform
==
Platforms.Android:
from
classes.android.base_case
import
AndroidTestCase
as
TestCase
from
classes.android.base_case
import
AndroidWithPreloadedTestCase
as
WithPreloadedTestCase
elif
platform
==
Platforms.WindowsPhone:
from
classes.wp.base_case
import
WindowsPhoneTestCase
as
TestCase
from
classes.wp.base_case
import
WindowsPhoneWithPreloadedTestCase
as
WithPreloadedTestCase
elif
platform
==
Platforms.iOS:
from
classes.ios.base_case
import
IosTestCase
as
TestCase
from
classes.ios.base_case
import
IosWithPreloadedTestCase
as
WithPreloadedTestCase
else:
from
interfaces.base_cases
import
WithPreloadedTestCase
raise
LookupError('Unknown
platform
%s'
%
platform)
59. Initial setup
59
Installed python on each node
Setup 3 nodes:
1. OS X with Xcode, iOS Simulators and Appium
2. Ubuntu with Android SDK, setup emulator and Appium
3. Windows 8.1 with Windows Phone SDK and Winium
60. Running tests
60
#
Common
setup
(language
specific)
pip
install
-‐r
requirements.txt
#
Android
on
Ubuntu
pip
install
-‐r
requirements-‐android.txt
PLATFORM=Android
nosetests
tests
-‐s
#
iOS
on
OS
X
PLATFORM=iOS
nosetests
tests
-‐s
#
Windows
Phone
on
Windows
set
PLATFORM=WindowsPhone
&&
nosetests
tests
-‐s
#
Or
run
tests
for
all
3
platforms
from
single
machine
that
is
connected
to
3
platform
specific
nodes