The Advanced Way to Run Functional Tests of a Native Mobile Application with Appium

A few years back, I was managing iOS client team, and one of my engineers integrated functional testing. We used Appium, and that was a hassle. It could take hours to make it working on a new developer’s machine or a new node for builds and tests. The number of steps you had to go through to set it up killed any enthusiasm, and it didn’t work in the end. Damn it…

Later, I started using React Native for all mobile development with a business logic. As of functional testing, I use detox for testing all React Native code, and I use WebDriverIO for testing which goes out of React Native functionality, for example to test “create an account and login flow with FB/Twitter/Google”.

The beauty of JS environment is that all developers have the same one as long as they have the same version of node and yarn. All package versions are fixed in yarn.lock. Why not to use the same approach and use WebDriverIO to test Native iOS or Android applications? Let me show you how to do it for iOS Native Application on your Mac.

You need to install node and yarn. Please follow the first part of this tutorial to install them.

You can use your own iOS Native project, but I recommend you to use mine to go through verified steps, make sure it works, and then do the same for your own project. Please check it out:

$ git clone
$ cd TMDb
$ git checkout tags/initial

To install WebDriverIO command line tools (everything is installed to local node_modules folder) run:

$ yarn add -D @wdio/cli

Run the command line configurator and follow the prompt:

$ yarn wdio config --yarn* Where is your automation backend located? - On my local machine
* Which framework do you want to use? - jasmine
* Do you want to run WebdriverIO commands synchronous or asynchronous? - sync
* Where are your test specs located? - leave default/blank
* Do you want WebdriverIO to autogenerate some test files? - Y
* Do you want to use page objects ( - n
* Are you using a compiler? - No
* Which reporter do you want to use?? - spec
* Do you want to add a service to your test setup? - Deselect chromedriver select appium
* What is the base url? - leave default/blank

In the end, it will install all other dependencies based on your answers and create wdio.conf.js file.

Update package.json file, to add scripts for building the application, and running the functional tests:

"scripts": {
"test:build": "xcodebuild -workspace ./TMDb.xcodeproj/project.xcworkspace -configuration release -scheme TMDb -sdk iphonesimulator -derivedDataPath build",
"test:run": "wdio wdio.conf.js"


  • ./TMDb.xcodeproj/project.xcworkspace - workspace path;
  • TMDb - build schema name;
  • build - build destination folder.

Now, you can build the app for testing; just run:

$ yarn test:build

If you do it for your own project, locate the app you’ve just built:

$ find ./build -name "*.app"
# ./build/Build/Products/Release-iphonesimulator/

Update capabilities section in wdio.conf.js file:

capabilities: [{
maxInstances: 1,
browserName: 'iOS',
platformName: 'iOS',
platformVersion: '14.0',
deviceName: 'iPhone 11',

automationName: 'XCUITest',
app: `${__dirname}/build/Build/Products/Release-iphonesimulator/`

Verify and fix if needed platformVersion and deviceName. If you setup your own project, update the app path to the one you’ve gotten in the previous step after the build.

Even though I provide an example for iOS, you can use the same approach for Android Native application. Here’s working Android capabilities section for wdio.conf.js in case you will do it for your Android project:

capabilities: [{
maxInstances: 1,
browserName: 'Android',
platformName: 'Android',
platformVersion: '10',
deviceName: 'emulator-5554',
app: `${__dirname}/app/build/outputs/apk/debug/app-debug.apk`,
appWaitActivity: 'com.tmdb.english_main.MainActivity'

You should have different wdio.conf.js file, for example wdio.conf.ios.js and, if you run the tests from the same folder for iOS and Android. Add two different scripts, like test:run:ios and test:run:android, with corresponding config paths in package.json.

Update test/specs/example.e2e.js with the following content (for TMDb example):

When you develop your own tests:

  • save them to test/specs folder. Use WebdriverIO documentation;
  • use XCode=>Open Developer Tool=>Accessibility Inspector to locate UI elements and their ids;
  • set accessibilityIdentifier for UI elements you cannot get an access by a label text;
  • use your favorite editor for JavaScript test files, like Visual Studio Code;
  • consider switching to TypeScript if you have a large team and long term project.

To run the tests:

$ yarn test:run

It takes time to run it for the first time, as it installs WebDriverAgent on the simulator. You should get:

Functional Automation in Action

Add build and node_modules to .gitignore.

The main point of the article is simplicity of running functional tests on any machine. As long as you have node and yarn, and Xcode installed on any Mac, after checking out the project, just open terminal, go the the project folder, and run:

$ yarn install
$ yarn test:build
$ yarn test:run