So you built a kickass iOS app. You install it on your iPhone, play around with it, perform some basic manual tests and everything simply works! You feel on top of the world and you move forward with developing the next big feature of your app while hearing angels singing in the background.
Then it hits you like a ton of bricks. With each new feature you add — a whole lot of testings need to be done as well. More deployments to your device — more manual testing — more time spent on testings instead of enjoying life.
This is where Appium comes into play. Appium, in its creators own words, is an open-source tool for automating native, mobile web, and hybrid applications on iOS and Android platforms. In simple words: Appium allows you to create automated tests for your app using Python so you won’t have to test it manually yourself.
Now that you are all pumped up and excited for the future, It’s time to get Appium for iOS testing using an iPhone simulator up and running!
As exciting as it may be to fire up your favorite text editor and start writing amazing tests, we first need to install some modules that will help us (and Appium) with the automation.
First, make sure you have PiP installed on your system by typing pip -V into the command line. You should get a result similar to the following:
pip 9.0.1 from /Users/johnnyt/.py/lib/python2.7/site-packages (python 2.7)
If for some reason you don't have pip installed, head over to https://pip.pypa.io/en/stable/installing/ for details on how to do so.
Next, create a folder to put all our tests and configuration files in, then create a text file named pip-reqs.txt containing all the packages we wish to install:
selenium==3.3.1
py==1.4.34
pytest==3.2.3
Appium-Python-Client==0.24
Why do we need these 4 packages you may ask?
Install all the packages using the following command:
pip wheel --wheel-dir wheelhouse -r pip-reqs.txt
Appium is installed using NPM. Yap, its that easy.
npm install -g appium
In order for your app to run in a simulator, it must be specifically compiled for that simulator. This is done using the xcodebuild command line tool inside the project’s folder. Let’s examine the following example:
xcodebuild -workspace SuperAwesomeApp.xcworkspace -scheme SuperAwesome -sdk iphonesimulator11.1
The command sets three required parameters for xcodebuild as follows:
xcodebuild -list
xcodebuild -showsdks
⚠️ Please note: Since we wish to use a simulator for our automated tests, we should use the iphonesimulator SDK option when building our app.
Once ran, a new folder called .app will be created containing your app and its related elements (debug code etc.). If you didn't change the default project values, the .app folder will be created under the following location:
~/Library/Developer/Xcode/DerivedData/<appname>-xxxxxxxxxx/Build/Products/debug-iphonesimulator/
⚠️ ** Please note**: xxxxxxx will be replaced by a random string.
Now that we have everything installed, and our app compiled just the right way, let’s get testing!
The basis to our automated testing is to have Appium boot up an iPhone simulator, deploy our app to it and finally run the app.
In the same folder you created in the Installing Python prerequisites step, create a new file named commonutils.py_ with the following code:
from appium import webdriver
import os
def set_up(self):
d_caps = {}
d_caps['platformName'] = 'iOS'
d_caps['platformVersion'] = '11.1'
d_caps['deviceName'] = 'iPhone 7'
d_caps['app'] = os.path.abspath('/users/johnnyt/Projects/super-awesome-app/DerivedData/SuperAwesome/Build/Products/Debug-iphonesimulator/SuperAwesome.app')
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', d_caps)
Let’s analyze what this code does:
import unittest
import time
from common_utils import set_up
class BasicTest(unittest.TestCase):
test_name = 'BasicTest'
driver = None
def test_basic_test(self):
set_up(self)
It’s quite simple to understand whats going on in here:
We are now ready to run our first test! Open your favourite terminal app and run appium server by simply typing appium and press enter. If all goes well you should see something similar to this:
Next, open another terminal window and run the test by typing the following:
pytest -v -s basic_test.py
A few seconds will go by and if the gods are smiling upon us a new iPhone simulator running our app will pop up and the test will pass.
If you take a look at the command line right now you would see that the simple test we created passed. This is because we didnt really test anything, we just told Appium to open a simulator and since it did it so gracefully — our test is considered a success.
A more useful test would be, for example, testing the login flow of our app. How would we go about do that you may ask? Well, the plan is as follows:
Now that we know what needs to be done, let’s get started.
In order to easily grab the fields and button we need to give them an id. In Xcode click on the login button and the email and password fields, switch to the Identity Inspector enter an identity under the Accessibility options:
At this point you will need to rebuild the app (as explained in the Preparing Your App for Appium section) so that Appium will be able to use the new ids.
Next, open the basictest.py_ file and add the following code inside the testbasictest method so it will look as follows:
def test_basic_test(self):
set_up(self)
email = self.driver.find_element_by_name("emailField")
email.clear()
email.send_keys("dixie@monize.com")
self.driver.back()
password = self.driver.find_element_by_name("passwordField")
password.clear()
password.send_keys("1234567")
self.driver.find_element_by_name("loginBtn").click()
time.sleep(5)
self.driver.find_element_by_id("logoutBtn")
Let’s analyze the code:
Let’s see this test in action:
And there you have it. A fully working test that actually tests something useful! From here on out — the world is your oyster. Take what you learnt here and go have fun with automated tests.
🔥 Special thanks to Noy Mizrahi for helping me with this post!