Problem: There is a perception among testers that getting started with mobile automation is hard.
Why this post?
I strongly believe that a tester must have a wide range of skills. You do not need to be an expert in all of them, but it is extremely important to have contemplated a spectrum of concepts and explored a variety of tools. The context under which you test will inform you of the specific choice of testing methodology and test tools to choose. The more options you are aware of, the better your context specific choice is going to be. In this regard, I began noticing that mobile testing has become somewhat of a niche among testers. Testers are reluctant to get started with mobile testing – probably because they think getting started involves a lot of time and effort. At Qxf2 Services, we have decided to tackle the problem head on. This post is the first in a series of quick, easily consumable tutorials geared towards hands-on testers looking to start exploring the mobile testing landscape.
NOTE: In this post we are concentrating only on the “getting started” phase. The tools your test team uses to solve the specific and unique problems can greatly vary. There is no one silver bullet.
Overview
For this post, we will show you how to get started with Selendroid and Python in less than 2 hours. Selendroid is a test automation framework which drives off the UI of Android native and hybrid applications (apps) and the mobile web. Tests are written using the Selenium 2 client API. Selendroid can be used on emulators and real devices. We will show you how to setup an Android emulator, launch a browser, click a link and verify the title of the new page that loads.
1. Download and install Android-Sdk
2. Setup your environment variables
3. Start the emulator
4. Write the Python test
5. Download and start Selendroid
6. Run the test
STEP 1: Download and Install Android-Sdk
From Android web site, download the latest Android-Sdk. This also installs the AVD Manager, a graphical user interface for creating and managing Android Virtual Devices (AVDs).
STEP 2: Setup your environment variables
Make sure you have Java Installed on your machine. Setup the following system environment variables:
ANDROID_HOME= $YOUR_SDK_INSTALL_PATH\sdk JAVA_HOME=$YOUR_JAVA_HOME (e.g.: C:\Program Files\Java\jdk1.8.0_05) |
Add ANDROID_HOME/tools, ANDROID_HOME/platform-tools and ANDROID_HOME/build-tools to your PATH environment variable.
STEP 3: Start the emulator
For this tutorial, we are choosing to use the Android emulator. If you do not have an Android device for testing, you can use an Android virtual device. After installing Android SDK and setting up your system variables, run the below command
android create avd --name Device Name --target android-19 --abi armeabi-v7a |
Where “name” Name of the new AVD created, “target” Target ID of the new AVD created and “abi” The CPU/ABI to use for the AVD. You can use the below command to display the list of all available targets. You can then use this details to update the “target” and “abi”:
android list target |
You can run the below command to view the AVD created:
android list avd |
You can run the below command to verify that the AVD is working:
emulator -avd Default |
STEP 4: Write the Python test
We are going to be using a chess website called Chessdom to write our test. We will launch a browser, click on the ‘Chess News’ link and verify the title of the page that loads. The code should look something like the snippet below
""" Qxf2 Services: Sample Python script to get started with Selendroid """ import unittest, time from selenium import webdriver from selenium.webdriver.common.touch_actions import TouchActions class FindElementTest(unittest.TestCase): def setUp(self): "Set up the Android Driver" self.driver = webdriver.Remote(desired_capabilities=webdriver.DesiredCapabilities.ANDROID) self.driver.implicitly_wait(30) def test_Launch_Chessdom(self): "Test the title of the Chess News page on Chessdom.com is correct" # Go to url:http://www.chessdom.com/ self.driver.get('http://www.chessdom.com/') time.sleep(5) #Click on the link "Chess News" ChessNews = self.driver.find_element_by_xpath("//a[@title='View all posts filed under Chess News' and text()='Chess News']") ChessNews.click() time.sleep(5) #Increase sleep time if your emulator has performance issues # Assert that the Page has title "Chess News | Chessdom" self.assertIn("Chess News | Chessdom", self.driver.title) def tearDown(self): "Tear down the test" self.driver.quit() if __name__ == '__main__': unittest.main() |
Why is chess there in this example? Because, I love chess. I named Qxf2 Services after Black’s fantastic 21st move in this masterpiece by Hikaru Nakamura.
STEP 5: Download and start Selendroid
Download Selendroid and cd to the folder where you downloaded the jar. Spin up a new command prompt and run the command below to start Selendroid
java -jar selendroid-standalone-0.10.0-with-dependencies.jar |
Selendroid-standalone will start an http server on port 4444 and will scan all Android virtual devices
STEP 6: Run the test
You can run the test script the normal way you do. We run it via the command prompt.
You can also view the test running in the Android emulator
There you have it! A tutorial to get you started with Selendroid in under two hours.
Note: To save time writing your mobile automation tests, we recommend you start out with our open-sourced test automation framework in Python.
I am a dedicated quality assurance professional with a true passion for ensuring product quality and driving efficient testing processes. Throughout my career, I have gained extensive expertise in various testing domains, showcasing my versatility in testing diverse applications such as CRM, Web, Mobile, Database, and Machine Learning-based applications. What sets me apart is my ability to develop robust test scripts, ensure comprehensive test coverage, and efficiently report defects. With experience in managing teams and leading testing-related activities, I foster collaboration and drive efficiency within projects. Proficient in tools like Selenium, Appium, Mechanize, Requests, Postman, Runscope, Gatling, Locust, Jenkins, CircleCI, Docker, and Grafana, I stay up-to-date with the latest advancements in the field to deliver exceptional software products. Outside of work, I find joy and inspiration in sports, maintaining a balanced lifestyle.
This is very awesome, and highly useful. I am just getting starting in automated testing, and I have a few questions. Do you know how easy this would be to set up on a Mac or Linux environment (I write my tests on my mac and execute them in a headless Linux environment with Firefox)? Also, so you know if there is an iOS equivelant, perhaps with the iOS simulator? Out if my company’s 50% mobile traffic, almost 90% of that is is iOS. Thanks, and and once again, very helpful!
Thanks! The SeleniumHQ blessed approaches to automating on Android and iOS are: Selendroid, ios-driver and Appium [1]. We will be writing about getting started with Appium soon (this week/next week) but not iOS specific yet.
[1] http://seleniumhq.wordpress.com/2013/12/24/android-and-ios-support/
Well, I figured out iOS, which is nice. But, when I tried to launch the test, I got this error (after waiting close to 2 minutes for it to start) –
SEVERE: Error while creating new session: For input string: “WVGA800”
java.lang.NumberFormatException: For input string: “WVGA800”
WVGA800 is the skin of the AVD that I created. Any idea what this means and how to resolve it? Thanks!
WVGA$NUMBER is used to describe the screen display resolution. Can you see if this link helps you past your error?
https://github.com/selendroid/selendroid/issues/287
Hi,
Can you please let me know what is the method to wait until to see the element?
I click on a button, it navigates to another page with some text, I need to write a wait method to see the text in the next page.
My app is a native app.
Thanks,
Praveen.
Praveen,
Here is a link for your reference.
Hello,
I have seen the above link, but its a java method. I am writing the code in python.
Please let me know, the method which wait until to see the element in python.
self.driver.implicitly_wait() is not working.
Hi,
Have you tried the following?
wait = WebDriverWait(self.driver,10)
condition = EC.text_to_be_present_in_element((By.TAG_NAME, “html”), “search”)
wait.until(condition)
This is still not working, can you please elt me know one thing? selendroid works on native app activity?
Because, when I tap Next button in my test app, it navigates to Device Administrators screen for requesting admin rights for my test app, so here I need to click on “Activate” button in Device Administrators screen. so clicking on this button using selendroid is not working. So my question is does it also work on device native inbuilt apps activity? if yes please let me know how to click on Activate button in Device Administrators screen screen.
Thanks,
Praveen
Any Answer for the above question? does Selendroid works for device native apps like Settings? Contacts, Messaging?
Praveen, Thanks for the great follow up question! Selendroid does have native app support. I am not sure about your specific use case of jumping between apps though. I believe you need to switch context when switching between apps – but I could be wrong. Do you have an example app that I could play around with?
If its easier, feel free to email me at mak@qxf2.com. And sorry for the delay in replying!
can you tell me where i have to write the python file
Hi Manivannan,
You can write your Python test anywhere on your machine where selendroid server is running
how script and emulator should interact?
Selendroid server uses adb commands to list all the available devices. Since we start selendroid server the script interacts with any emulator or device available.
Refer to the below link for more details
http://selendroid.io/architecture.html
Hi, Thanks for great tutorial…
I have used the same code to run android emulator, but Selendroid webapp is launching and immediately crashing. So browser is not launching “chessdom” page.
At the end python script gives an error “WebDriverException: Message: Error communicating with the remote browser. It have died.
Build info: version: ‘unknown’, revision: ‘unknown’, time: ‘unknown’
System info: host: ‘GISI-xxx-198′, ip: ’10.xx.xxx.208’, os.name: ‘Windows 7’,
.arch: ‘amd64’, os.version: ‘6.1’, java.version: ‘1.8.0_31’
Driver info: driver.version: SelendroidStandaloneDriver.
Could any body please guide how to resolve this issue. Thanks.
What is the version of the SelendroidStandaloneDriver?There might be a mismatch between Selenium and Selendroid.
Can you do the following:
jar -xvf selendroid-standalone–with-dependencies.jar
Check the version in pom.xml in the \META-INF\maven\org.seleniumhq.selenium\
Thanks for the reply.
Some observation below:
Yes, selenium installed version was 2.44, but seleandroid_14 (in pom.xml) has 2.43.1. However I didn’t get selenium for 2.43.2, but tried on 2.43.0 same issue exists.
So I tried with selandroid_10 as your example with selenium version 2.41.0, but below error encountered.
Tried on Android Emulator:
Throws an error “Seleandroid server on the device didn’t came up after 20s”
Error message:
======================================================================
ERROR: test_Launch_Chessdom (__main__.FindElementTest)
Test the title of the Chess News page on Chessdom.com is correct
———————————————————————-
Traceback (most recent call last):
File “D:\Scrap\Script1.py”, line 13, in setUp
self.driver = webdriver.Remote(desired_capabilities=webdriver.DesiredCapabi
lities.ANDROID)
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\webdriver.py”, line 72, in __init__
self.start_session(desired_capabilities, browser_profile)
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\webdriver.py”, line 115, in start_session
‘desiredCapabilities’: desired_capabilities,
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\webdriver.py”, line 166, in execute
self.error_handler.check_response(response)
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\errorhandler.py”, line 164, in check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: u”Selendroid server on the device didn’t came up af
ter 20sec:\nio.selendroid.exceptions.SelendroidException: Selendroid server on t
he device didn’t came up after 20sec:\r\n\tat io.selendroid.server.model.Selendr
oidStandaloneDriver.createNewTestSession(SelendroidStandaloneDriver.java:311)\r\
n\tat io.selendroid.server.handler.CreateSessionHandler.handle(CreateSessionHand
ler.java:42)\r\n\tat io.selendroid.server.SelendroidServlet.handleRequest(Selend
roidServlet.java:142)\r\n\tat io.selendroid.server.BaseServlet.handleHttpRequest
(BaseServlet.java:70)\r\n\tat org.webbitserver.netty.NettyHttpControl.nextHandle
r(NettyHttpControl.java:78)\r\n\tat org.webbitserver.netty.NettyHttpControl.next
Handler(NettyHttpControl.java:62)\r\n\tat org.webbitserver.handler.PathMatchHand
ler.handleHttpRequest(PathMatchHandler.java:33)\r\n\tat org.webbitserver.netty.N
ettyHttpControl.nextHandler(NettyHttpControl.java:78)\r\n\tat org.webbitserver.n
etty.NettyHttpControl.nextHandler(NettyHttpControl.java:62)\r\n\tat org.webbitse
rver.handler.DateHeaderHandler.handleHttpRequest(DateHeaderHandler.java:21)\r\n\
tat org.webbitserver.netty.NettyHttpControl.nextHandler(NettyHttpControl.java:78
)\r\n\tat org.webbitserver.netty.NettyHttpControl.nextHandler(NettyHttpControl.j
ava:62)\r\n\tat org.webbitserver.handler.ServerHeaderHandler.handleHttpRequest(S
erverHeaderHandler.java:25)\r\n\tat org.webbitserver.netty.NettyHttpControl.next
Handler(NettyHttpControl.java:78)\r\n\tat org.webbitserver.netty.NettyHttpContro
l.nextHandler(NettyHttpControl.java:67)\r\n\tat org.webbitserver.netty.NettyHttp
ChannelHandler$2.run(NettyHttpChannelHandler.java:72)\r\n\tat java.util.concurre
nt.ThreadPoolExecutor.runWorker(Unknown Source)\r\n\tat java.util.concurrent.Thr
eadPoolExecutor$Worker.run(Unknown Source)\r\n\tat java.lang.Thread.run(Unknown
Source)\r\n”
Tried on Samsung Device:
Throws an error “Error occurred while starting selendroid-server o
n the device”. May be it is related to some instrumentation error.
Errog log:
File “D:\Scrap\Script1.py”, line 13, in setUp
self.driver = webdriver.Remote(desired_capabilities=webdriver.DesiredCapabi
lities.ANDROID)
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\webdriver.py”, line 72, in __init__
self.start_session(desired_capabilities, browser_profile)
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\webdriver.py”, line 115, in start_session
‘desiredCapabilities’: desired_capabilities,
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\webdriver.py”, line 166, in execute
self.error_handler.check_response(response)
File “C:\Python27\lib\site-packages\selenium-2.41.0-py2.7.egg\selenium\webdriv
er\remote\errorhandler.py”, line 164, in check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: u’Error occurred while starting selendroid-server o
n the device\nio.selendroid.exceptions.SelendroidException: Error occurred while
starting selendroid-server on the device\r\n\tat io.selendroid.android.impl.Abs
tractDevice.startSelendroid(AbstractDevice.java:235)\r\n\tat io.selendroid.serve
r.model.SelendroidStandaloneDriver.createNewTestSession(SelendroidStandaloneDriv
er.java:290)\r\n\tat io.selendroid.server.handler.CreateSessionHandler.handle(Cr
eateSessionHandler.java:42)\r\n\tat io.selendroid.server.SelendroidServlet.handl
eRequest(SelendroidServlet.java:142)\r\n\tat io.selendroid.server.BaseServlet.ha
ndleHttpRequest(BaseServlet.java:70)\r\n\tat org.webbitserver.netty.NettyHttpCon
trol.nextHandler(NettyHttpControl.java:78)\r\n\tat org.webbitserver.netty.NettyH
ttpControl.nextHandler(NettyHttpControl.java:62)\r\n\tat org.webbitserver.handle
r.PathMatchHandler.handleHttpRequest(PathMatchHandler.java:33)\r\n\tat org.webbi
tserver.netty.NettyHttpControl.nextHandler(NettyHttpControl.java:78)\r\n\tat org
.webbitserver.netty.NettyHttpControl.nextHandler(NettyHttpControl.java:62)\r\n\t
at org.webbitserver.handler.DateHeaderHandler.handleHttpRequest(DateHeaderHandle
r.java:21)\r\n\tat org.webbitserver.netty.NettyHttpControl.nextHandler(NettyHttp
Control.java:78)\r\n\tat org.webbitserver.netty.NettyHttpControl.nextHandler(Net
tyHttpControl.java:62)\r\n\tat org.webbitserver.handler.ServerHeaderHandler.hand
leHttpRequest(ServerHeaderHandler.java:25)\r\n\tat org.webbitserver.netty.NettyH
ttpControl.nextHandler(NettyHttpControl.java:78)\r\n\tat org.webbitserver.netty.
NettyHttpControl.nextHandler(NettyHttpControl.java:67)\r\n\tat org.webbitserver.
netty.NettyHttpChannelHandler$2.run(NettyHttpChannelHandler.java:72)\r\n\tat jav
a.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)\r\n\tat java.util
.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)\r\n\tat java.lang.Thre
ad.run(Unknown Source)\r\nCaused by: java.lang.Throwable: android.util.AndroidEx
ception: INSTRUMENTATION_FAILED: io.selendroid.io.selendroid.androiddriver/io.se
lendroid.ServerInstrumentation\n\tat com.android.commands.am.Am.runInstrument(Am
.java:865)\n\tat com.android.commands.am.Am.onRun(Am.java:282)\n\tat com.android
.internal.os.BaseCommand.run(BaseCommand.java:47)\n\tat com.android.commands.am.
Am.main(Am.java:76)\n\tat com.android.internal.os.RuntimeInit.nativeFinishInit(N
ative Method)\n\tat com.android.internal.os.RuntimeInit.main(RuntimeInit.java:24
8)\n\tat dalvik.system.NativeStart.main(Native Method)\n\nDetails:\nINSTRUMENTAT
ION_STATUS: id=ActivityManagerService\nINSTRUMENTATION_STATUS: Error=Unable to f
ind instrumentation info for: ComponentInfo{io.selendroid.io.selendroid.androidd
river/io.selendroid.ServerInstrumentation}\nINSTRUMENTATION_STATUS_CODE: -1\nand
roid.util.AndroidException: INSTRUMENTATION_FAILED: io.selendroid.io.selendroid.
androiddriver/io.selendroid.ServerInstrumentation\n\tat com.android.commands.am.
Am.runInstrument(Am.java:865)\n\tat com.android.commands.am.Am.onRun(Am.java:282
)\n\tat com.android.internal.os.BaseCommand.run(BaseCommand.java:47)\n\tat com.a
ndroid.commands.am.Am.main(Am.java:76)\n\tat com.android.internal.os.RuntimeInit
.nativeFinishInit(Native Method)\n\tat com.android.internal.os.RuntimeInit.main(
RuntimeInit.java:248)\n\tat dalvik.system.NativeStart.main(Native Method)\n\r\n\
t… 20 more\r\n’
Kindly guide me how to resolve these issues….Thanks in Advance
Guruswamy,
You can try the following:
-Please start selendroid-standalone with the flag -forceReinstall.
https://github.com/appium/appium/issues/3227 also lists similar issue, please take a look.
Have you followed the guidelines for ‘using emulator’ given here -http://selendroid.io/setup.html
Hope this helps.
Thanks
Vrushali
Hi,
Am new to selondroid , am starting automation with python for android device. I have a query that how do i launch web server or chrome on android device using this.
ex:- open chrome on real android device >launch local host:8080>enter Password and click on login> click on some buttons and change settings..
any help
Hi Rashmi,
For running your test on Chrome you need to use ChromeDriver – WebDriver for Chrome.
Please refer to this link below for more details
https://sites.google.com/a/chromium.org/chromedriver/getting-started/getting-started—android
Once you download the ChromeDriver on your system and start the ChromeDriver server. It will print the port it is listening on:
Starting ChromeDriver (v2.10.267521) on port 9515
Then you can update the script as mentioned below and launch any site and perform actions on it.
desired_capabilities = {‘chromeOptions’: {‘androidPackage’: ‘com.android.chrome’,}}
self.driver = webdriver.Remote(‘http://localhost:9515’, desired_capabilities)
Please let me know, the method which wait until to see the element in python.
self.driver.implicitly_wait(150) is not working.
I see the python API doc for Webdriver, it seems default the unit is second. when I setting the seconds to 150 ,it also is not working ?
Hi Nancy,
Implicit wait should have worked. I am not sure why it isn’t. Probably its because the element is present in background and is not visible.
You can also try Explicit Wait. An explicit wait is code you define to wait for a certain condition to occur before proceeding further in the code.
For details on how to implement it you can refer to this link http://selenium-python.readthedocs.org/waits.html.
Try the method “visibility_of_element_located”. Let me know if this helps?