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 second 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.
A little bit of history
On the eve of Christmas 2013, Selenium officially retired their own AndroidDriver and iPhoneDriver in favour of Selendroid, iosdriver and Appium. In an earlier post we explored using Selendroid and Python. In this post, we will help you get started with Appium.
Appium is an open-source tool you can use to automate mobile native, mobile web, and mobile hybrid applications on iOS and Android platforms. Appium is “cross-platform”: it allows you to write tests on multiple platforms (iOS, Android), using the same API. This enables a large or total amount of code reuse between iOS and Android test suites.
Appium setup
Here are the steps to setup Appium on Windows 7 and use it with Android emulator.
1. Download the latest Appium
I have used appium-desktop-Setup-1.5.0-ia32.exe. You can run the exe to install the appium desktop app
2. Download and Install Android Studio
Once you install Android Studio make sure the AVD Manager is also installed as we are going to run our tests on an emulator. Set ANDROID_HOME to be your Android SDK path and add the tools and platform-tools folders to your PATH variable. I could find the Android SDK installed on the below-mentioned path
$\AppData\Local\Android\Sdk
3. Install the Java JDK
Set JAVA_HOME to your JDK folder
4. Install the Python client library
There are client libraries (in Java, Ruby, Python, PHP, JavaScript, and C#) which support Appium’s extensions to the WebDriver protocol. When using Appium, you want to use these client libraries instead of your regular WebDriver client. I have used the Appium Python client available here. Assuming you have pip installed on your machine, you can use the following command to install it
pip install Appium-Python-Client |
Woot! You are now set up. Next stop: launch the emulator and start the Appium server.
5. Start the Android Virtual Device (AVD) Manager
Start the Android Studio and launch the Android Virtual Device (AVD) Manager from by clicking on the link as shown in the screenshot below.
Create an emulator with the preferences you need and launch it using the start button
6. Start the Appium server console
Start the Appium server console by double clicking on the Appium file.
7. Launch the Appium node server
Click on the ‘rocket’ icon to launch the Appium node server
Your first test using Appium
For this test we will use one of my favorite Android apps – the highly recommended Chess Free application created by the UK based AI Factory. For this blog post, we will pretend that our test is to launch the application and click on “PLAY” button.
1. Obtain the .apk for the application under test
We obtained the .apk for Chess Free over here. Copy the chess application to a directory of your choice. I used ($Directory_Of_My_Choice\apps\Chess Free.apk )
2. Peek into the AndroidManifest.xml
To write the test, you need two pieces of information specific to your application:
a) Java package of the Android app you want to run
b) Activity name for the Android activity you want to launch your package
You can get this information by running the following command
ANDROID_HOME\sdk\build-tools\android-4.4.2>aapt dump badging path_to_apk_file |
Another approach is using the AndroidManifest.xml which is present in the root directory of all Android applications and has the information we need. You can use Android Studio to view the AndroidManifest.xml file. Go to Build/Analyze APK and select your apk. Then you can see the content of the AndroidManifset file.
package="uk.co.aifactory.chessfree" and android:name=".ChessFreeActivity" |
3. Write the test
Create a test script (android_chess.py) in $Directory_Of_My_Choice based on the snippet below. Pay particular attention to the setup() method.
""" Qxf2: Example script to run one test against the Chess Free app using Appium The test will: - launch the app - click the 'PLAY!' button """ import os import unittest from appium import webdriver from time import sleep class ChessAndroidTests(unittest.TestCase): "Class to run tests against the Chess Free app" def setUp(self): "Setup for the test" desired_caps = {} desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '8.0' desired_caps['deviceName'] = 'Pixel' # Returns abs path relative to this file and not cwd desired_caps['app'] = os.path.abspath(os.path.join(os.path.dirname(__file__),'apps/Chess Free.apk')) desired_caps['appPackage'] = 'uk.co.aifactory.chessfree' desired_caps['appActivity'] = '.ChessFreeActivity' self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) def tearDown(self): "Tear down the test" self.driver.quit() def test_single_player_mode(self): "Test the Chess app launches correctly and click on Play button" element = self.driver.find_element_by_id("uk.co.aifactory.chessfree:id/ButtonPlay") element.click() sleep(5) #---START OF SCRIPT if __name__ == '__main__': suite = unittest.TestLoader().loadTestsFromTestCase(ChessAndroidTests) unittest.TextTestRunner(verbosity=2).run(suite) |
4. Run the test
Run the script android_chess.py. The chess application is launched in the test emulator
5. Check the result
Celebrate a little – you just upgraded your skills by a little bit in a very short span of time!
There you have it! You have just run your first mobile automated test with Appium and Python. If you are looking for Python based mobile automation framework, check out our open-sourced GUI and API automation framework based on the page object model. Happy exploring from Qxf2 Services!
P.S.: As a chess fanatic, I think it is a crime to test chess applications in an automated fashion. I sincerely believe infinite manual testing is the only correct way to test chess applications 😉
P.P.S: We were pleasantly surprised by positive reaction we got to our last tutorial on mobile application testing with Selendroid. Please chime in on the direction you want our future blog posts to go. We will try our best to keep churning out useful posts for testers.
Hire QA consultants from Qxf2
This is an extremely old article but as you can see, Qxf2 was an early adopter of Appium. Not only did we work with Appium, we shared our learnings with the QA community as well. This has been our culture and over the years we have improved and stayed in touch with the rapid changes in the software space. In fact, we have innovated in the QA services domain too. Qxf2 offer several top-notch, unique testing services aimed towards startups that most folks are not aware of. So, if you are working at a startup or on an early-stage product, browse our services and get in touch. After all, every team benefits from having one good technical tester!
My journey as a tester started at Sun Microsystems (now Oracle). I was part of the testing and sustaining team for the Portal Server and Identity Management products. My first assignment was to test the Rewriter module. I enjoyed understanding the big picture, writing test cases, finding bugs and sometimes suggesting the fix too! I was hooked onto testing. Testing felt natural and intuitive to me. I am technically inclined and can write automation in Java, C++, Perl and Python. I am well versed with SilkTest, Selenium, Appium and Selendroid. I am a Computer Science graduate from BITS-Pilani. I love travelling and listening to music.
The idea behind UI automation is to test the app as a user would. But i think, reusing test code is going to be a challenge when comparing web automation to native app automation. To test with more than one Android device locally, you need to have one Appium server per device. Good article.
Thanks for the comments! This post was just on getting started with mobile automation using appium. You can also run your test directly on cloud using Saucelabs. You can refer to our blog on Mobile Automation using appium and sauce-labs.
Hi, Thank you for the useful posts.I am just starting on automation with python 2.7 and appium and AWS device farm in my company.Please could you provide some posts for these to guide me as a starter.
Hi Rajkhowa,
I have not tried this. But i found this link on how to test an ios app on AWS device farm using Appium. This example is using Java. Probably you can refer to this in case you haven’t already had a look at it.
Thanks & Regards
Avinash Shetty
If any steps to setup Appium on Ubuntu and use it with Android emulator can be provided, then it would be of great help.
Aravind, I have not tried getting Appium on Ubuntu. I’m adding it to my to do list. I will try to install Appium on Ubuntu in the next 3 weeks. I’m giving you a high level answer here just in case you are in a hurry.
Since I am not in a position to try this right away, I did some extra high level research. Appium is written in JavaScript and powered by Node.js. There is a dependency on grunt too – which is like (not exactly but like) a build tool for JavaScript. Grunt lets JavaScript developers automate repetitive tasks like minifying scripts, running tests, etc. Node has its own eco system and uses NPM (Node Package Manager) to make installations easy. Its like APT for Ubuntu. Hopefully this gives you better context as you execute steps listed online.
I did Google around for common pitfalls and found these:
a) few people have trouble because they were running older versions of node. Apparently you need node 0.1 and above
b) few people warn that appium may not work if you installed node with sudo user
All in all, this answer on stackoverflow seems to be safest approach to installing Appium on Ubuntu. If you solve this problem before me, please post your answer here.
https://www.built.io/blog/2015/03/start-automating-native-ios-testing-with-appium-using-node-js/
I like your comment If any steps to setup Appium on Ubuntu and use it with Android emulator can be provided, then it would be of great help.
Thanks a lot.
Very useful article.
I want to learn “appium” ,i am a java programmer and i have knowledge on Webdriver ,can anybody help me to learn Appium.
Thanks in advance…….
Madhubabu, our experience with Java and Appium is extremely limited. However, one thing that helped us get started with Appium and Python was the concept behind Appium. Think of Appium as three parts:
1. Appium implements a some subset of webdriver methods (technically the REST API of webdriver aka webdriver JSON wire protocol).
2. Appium lets you interface with mobile devices by extending this webdriver implementation.
3. Appium also has added some functionality unique to mobile devices – swipe, flick, etc.
If you are already familiar with webdriver, I would suggest that you start with a simple app. Then figure out how to set the “desired capabilities”. Finally figure out the different webdriver calls implemented by Appium. Hope this helps!
Thanks,Article was really Helpful,though i was new to selenium i was able to run the Appium.
Hi ,
I am doing ioS Mobile automation testing for Native application.
I am getting an system generated location alert “… would like to use your Current Location”while opening the application in simulator . I am not able to handle this with Selenium as i am not able to capture this alert box using Inspector .
Is there any way to handle this with the help of capabilities (while setting the capabilities ) .I am using the below code :
capabilities.setCapability(CapabilityType.VERSION, “7.0”);
capabilities.setCapability(CapabilityType.PLATFORM, “Mac”);
capabilities.setCapability(“Device”, “iPhone Simulator”);
capabilities.setCapability(“app”,”/Users/test/EclipseMediaSourceTree/EclipseMedia/build/Release-iphonesimulator/EclipseMedia.app”);*/
//capabilities.setCapability(“app”,”sauce:storage:EclipseMedia.app.zip”);
try{
driver = new RemoteWebDriver(
new URL(remoteDriverURL), capabilities);
}
I am using Java + Appium + Web Driver +Sikuli.
Please help on this .
Priya, can you check if adding capabilities.setCapability(“autoAcceptAlerts”, true); works with your version of Appium?
Hi there, I am new to Appium. I followed all the steps and when I was running it I keep getting some URLError. Do you know what I missed? Thx very much!
This is what I got from the console:
test_single_player_mode (__main__.ChessAndroidTests)
Test the Single Player mode launches correctly … ERROR
======================================================================
ERROR: test_single_player_mode (__main__.ChessAndroidTests)
Test the Single Player mode launches correctly
———————————————————————-
Traceback (most recent call last):
File “C:\Users\bonnie.donnels\workspace\Emn8_automation\BKLoyalty\Test_Appium\testappium.py”, line 42, in setUp
self.driver = webdriver.Remote(‘http://localhost:4723/wd/hub’, desired_caps)
File “C:\Python27\Lib\site-packages\appium\webdriver\webdriver.py”, line 35, in __init__
super(WebDriver, self).__init__(command_executor, desired_capabilities, browser_profile, proxy, keep_alive)
File “C:\Python27\Lib\site-packages\selenium\webdriver\remote\webdriver.py”, line 73, in __init__
self.start_session(desired_capabilities, browser_profile)
File “C:\Python27\Lib\site-packages\selenium\webdriver\remote\webdriver.py”, line 121, in start_session
‘desiredCapabilities’: desired_capabilities,
File “C:\Python27\Lib\site-packages\selenium\webdriver\remote\webdriver.py”, line 171, in execute
response = self.command_executor.execute(driver_command, params)
File “C:\Python27\Lib\site-packages\selenium\webdriver\remote\remote_connection.py”, line 349, in execute
return self._request(command_info[0], url, body=data)
File “C:\Python27\Lib\site-packages\selenium\webdriver\remote\remote_connection.py”, line 417, in _request
resp = opener.open(request)
File “C:\Python27\Lib\urllib2.py”, line 404, in open
response = self._open(req, data)
File “C:\Python27\Lib\urllib2.py”, line 422, in _open
‘_open’, req)
File “C:\Python27\Lib\urllib2.py”, line 382, in _call_chain
result = func(*args)
File “C:\Python27\Lib\urllib2.py”, line 1214, in http_open
return self.do_open(httplib.HTTPConnection, req)
File “C:\Python27\Lib\urllib2.py”, line 1184, in do_open
raise URLError(err)
URLError:
———————————————————————-
Ran 1 test in 1.009s
FAILED (errors=1)
My hunches based on your error is that:
1. Appium server is not up and running (steps 6 & 7 in the Appium Setup section)
2. Appium server is running on a port other than 4723 (use netstat or TCPView on Windows to confirm)
3. localhost may not be getting resolved to 127.0.0.1 (try changing your URL from http://localhost:4723/wd/hub to http://127.0.0.1:4723/wd/hub and try)
Let me know if none of the hunches are right and we can go looking for more possibilities.
Thank so much!! I made sure that the Appium server is running correctly and also I checked port 4723 which is working fine. Now, I have another issue.
I keep getting the following error:
error: Unhandled error: Error: ENOENT, no such file or directory ‘C:\android_sdk_adt_bundle\android_sdk;\build-tools’
First, I don’t find ‘ENOENT’ in the directory; Second, I do not know why there is ‘;’ after … android_sdk directory.
So now I am facing a new problem.
Thanks very much!
ENOENT error is NodeJS complaining. Can you check these two things:
1. (highly likely) Does your ANDROID_HOME has an extra semi-colon at the end? If it does, remove the semi-colon, restart the appium server, open up a new command prompt and then try running the test again.
2. (unlikely but possible) Does your PATH variable have android related paths that have a spurious semi-colon i.e., a semi-colon that is NOT being used as a separator between two paths.
Thanks again!! Now it works. I had a ‘;’ in the end of the path (C:\android_sdk_adt_bundle\android_sdk;’ of ANDROID_HOME. I took out the ‘;’.
The problem is now resolved, although I didn’t have an extra ‘;’ to begin with and having one ‘;’ in the end of the path should not be a problem?
Thanks very much again, I appreciate it.
Hi ,
I am new to this i am getting the error below: can you help me out. i did try the above solution but still not working.
======================================================================
ERROR: test_single_player_mode (__main__.ChessAndroidTests)
Test the Single Player mode launches correctly
———————————————————————-
Traceback (most recent call last):
File “C:\BSG\Android\adt-bundle-windows-x86_64-20130522\android_chess.py”, line 26, in setUp
self.driver = webdriver.Remote(‘http://127.0.0.1:4723/wd/hub’, desired_caps)
File “C:\Python27\lib\site-packages\appium\webdriver\webdriver.py”, line 35, in __init__
super(WebDriver, self).__init__(command_executor, desired_capabilities, browser_profile, proxy, keep_alive)
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\webdriver.py”, line 73, in __init__
self.start_session(desired_capabilities, browser_profile)
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\webdriver.py”, line 121, in start_session
‘desiredCapabilities’: desired_capabilities,
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\webdriver.py”, line 173, in execute
self.error_handler.check_response(response)
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\errorhandler.py”, line 164, in check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: u”A new session could not be created. (Original error: Bad app: C:\\BSG\\Android\\adt-bundle-windows-x86_64-20130522\\Chess Free.apk. App paths
tall dir, or a URL to compressed file, or a special app name. cause: Error: Error locating the app: ENOENT, stat ‘C:\\BSG\\Android\\adt-bundle-windows-x86_64-20130522\\Ches
———————————————————————-
Ran 1 test in 0.105s
Selva, can you post the entire error message starting from raise exception_class(message, screen, stacktrace). It looks like your last few lines were not copy pasted fully. Also, please post the version of Appium you installed.
My best guesses without seeing the exact message is that:
1. (likely) Your script is pointing to the wrong app path. The app path in our script is set as:
desired_caps[‘app’] = os.path.abspath(os.path.join(os.path.dirname(__file__),’apps/Chess Free.apk’)) where
__file__ is the Python script you are executing and present in lets say $Directory_Of_My_Choice
The .apk is expected to be in $Directory_Of_My_Choice\apps\Chess Free.apk.
So either make sure that your directory structure matches what is set in desired_caps[‘app’] or change desired_caps[‘app’] to match where your app is present.
2. (unlikely) If the problem is intermittent, it may just be that you need to add a appWaitActivity to your desired capabilities.
Thanks for getting back to me. I did check the path and version. Here is the full details.
I am using appium version 1.0.0 as you suggested above
my scripts file is in the the below path
c:\
my app is in the below directory
C:\BSG\apps\ChesssFree.apk
my scripts:
=========================================
“””
Qxf2: Example script to run one test against the Chess Free app using Appium
The test will:
– launch the app
– click the ‘PLAY!’ button
– choose single player mode
“””
import os
import unittest
from appium import webdriver
from time import sleep
class ChessAndroidTests(unittest.TestCase):
“Class to run tests against the Chess Free app”
def setUp(self):
“Setup for the test”
desired_caps = {}
desired_caps[‘platformName’] = ‘Android’
desired_caps[‘platformVersion’] = ‘4.4.2’
desired_caps[‘deviceName’] = ’emulator-5554′
# Returns abs path relative to this file and not cwd
desired_caps[‘app’] = os.path.abspath(os.path.join(os.path.dirname(__file__),’BSG/Chess Free.apk’))
desired_caps[‘appPackage’] = ‘uk.co.aifactory.chessfree’
desired_caps[‘appActivity’] = ‘.ChessFreeActivity’
self.driver = webdriver.Remote(‘http://127.0.0.1:4723/wd/hub’, desired_caps)
def tearDown(self):
“Tear down the test”
self.driver.quit()
def test_single_player_mode(self):
“Test the Single Player mode launches correctly”
element = self.driver.find_element_by_name(“PLAY!”)
element.click()
self.driver.find_element_by_name(“Single Player”).click()
textfields = self.driver.find_elements_by_class_name(“android.widget.TextView”)
self.assertEqual(‘MATCH SETTINGS’, textfields[0].text)
#—START OF SCRIPT
if __name__ == ‘__main__’:
suite = unittest.TestLoader().loadTestsFromTestCase(ChessAndroidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
=============================================
here is the error:
C:\>android_chess.py
test_single_player_mode (__main__.ChessAndroidTests)
Test the Single Player mode launches correctly … ERROR
======================================================================
ERROR: test_single_player_mode (__main__.ChessAndroidTests)
Test the Single Player mode launches correctly
———————————————————————-
Traceback (most recent call last):
File “C:\android_chess.py”, line 26, in setUp
self.driver = webdriver.Remote(‘http://127.0.0.1:4723/wd/hub’, desired_caps)
File “build\bdist.win32\egg\appium\webdriver\webdriver.py”, line 35, in __init__
super(WebDriver, self).__init__(command_executor, desired_capabilities, browser_profile, proxy, keep_alive)
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\webdriver.py”, line 73, in __init__
self.start_session(desired_capabilities, browser_profile)
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\webdriver.py”, line 121, in start_session
‘desiredCapabilities’: desired_capabilities,
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\webdriver.py”, line 173, in execute
self.error_handler.check_response(response)
File “C:\Python27\lib\site-packages\selenium-2.42.1-py2.7.egg\selenium\webdriver\remote\errorhandler.py”, line 164, in check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: u”A new session could not be created. (Original error: Bad app: C:\\apps\\Chess Free.apk. App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file,
special app name. cause: Error: Error locating the app: ENOENT, stat ‘C:\\apps\\Chess Free.apk’)”
———————————————————————-
Ran 1 test in 0.194s
FAILED (errors=1)
C:\>
This is the appium windows error:
> Starting Node Server
> info: Welcome to Appium v1.0.0 (REV f0a00fab2335fa88cb355ab4dc43a9cd3f3236c0)
> info: Appium REST http interface listener started on 127.0.0.1:4723
> info: socket.io started
> info: Non-default server args: {“address”:”127.0.0.1″,”logNoColors”:true,”avd”:”appium”}
> ERROR: debug: Appium request initiated at /wd/hub/session
> info: Using local app from desired caps: C:\apps\Chess Free.apk
> ERROR: debug: Request received with params: {“desiredCapabilities”:{“deviceName”:”emulator-5554″,”app”:”C:\\apps\\Chess Free.apk”,”platformVersion”:”4.4.2″,”appPackage”:”uk.co.aifactory.chessfree”,”platformName”:”Android”,”appActivity”:”.ChessFreeActivity”}}
> info: Got configuration error, not starting session
> ERROR: error: Failed to start an Appium session, err was: Error: Bad app: C:\apps\Chess Free.apk. App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name. cause: Error: Error locating the app: ENOENT, stat ‘C:\apps\Chess Free.apk’
> info: Cleaning up appium session
> info: Error: Bad app: C:\apps\Chess Free.apk. App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name. cause: Error: Error locating the app: ENOENT, stat ‘C:\apps\Chess Free.apk’
> at null. (C:\BSG\Appium\AppiumForWindows-1.0.0\AppiumForWindows\node_modules\appium\lib\devices\android\android-common.js:53:13)
> at C:\BSG\Appium\AppiumForWindows-1.0.0\AppiumForWindows\node_modules\appium\lib\devices\device.js:70:16
> at Object.oncomplete (fs.js:107:15)
> info: Responding to client with error: {“status”:33,”value”:{“message”:”A new session could not be created. (Original error: Bad app: C:\\apps\\Chess Free.apk. App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name. cause: Error: Error locating the app: ENOENT, stat ‘C:\\apps\\Chess Free.apk’)”,”origValue”:”Bad app: C:\\apps\\Chess Free.apk. App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name. cause: Error: Error locating the app: ENOENT, stat ‘C:\\apps\\Chess Free.apk'”},”sessionId”:null}
> POST /wd/hub/session 500 42ms – 632b
I hope this will help.
Thanks
Please try changing desired caps to this:
desired_caps[‘app’] = os.path.abspath(os.path.join(os.path.dirname(__file__),’BSG/apps/Chess Free.apk’))
I think what is going on right now is that Appium is looking for the apk in C:/BSG/. You can make Appium look for the app in C:/BSG/apps by making the above change.