How to use Appium for automated app testing

Testing plays a key role during the development of an app, and if done properly, can save a lot of time. Manually repeating tests is costly and time consuming, that’s why test automation frameworks were created. Appium is one of the more popular test automation frameworks in the mobile world. It’s an open source framework for use with native, hybrid and mobile web apps and is very well documented.Appium is a powerful framework that enables you to write tests independently from your app. Tests can be written in Java, Objective-C, JavaScript (Node), PHP, Python, Ruby, C#, Clojure, or Perl with the Selenium WebDriver API and language-specific client libraries.

How to use Appium

Appium comes with three tools:

Appium server

Appium desktop

Appium inspector

Appium server

Appium server is a HTTP REST API which is responsible for detecting and interacting with test devices. Appium supports both emulators and real devices. Nowadays Appium it’s integrated into Gitlab CI, AWS, Bitrise and other cloud applications. Using the API you will also be able to completely write your own integration if needed.Appium

Appium desktop

Desktop is an app for Mac, Windows, and Linux which gives you the power of the Appium automation server wrapped in a beautiful and flexible UI.

Appium Inspector

Appium inspector is a tool that can be used to inspect elements of a mobile app. When writing mobile tests you need to identify UI elements by certain ids and with Appium inspector you can find those ids without having the source code.

Once the Appium server is running you can interact with its API using one of the previously mentioned programming languages or using Appium inspector.

Hier is de Engelse vertaling van de alinea's, met behoud van de strakke lay-out en opbouw die perfect aansluit bij de richtlijnen uit image_5e4a3e.png:

Appium Desired Capabilities: What are they?

Before you start testing, you need to understand what Appium’s Desired Capabilities are. This is essentially a JSON document sent by the Appium client to the server as soon as a new automation session is requested. This document contains crucial data about how your session should run. Think of things like the device you want to use, which app needs to be launched, whether the app should be uninstalled beforehand, and which browser you want to test. Appium supports virtually all emulators, physical devices, and browsers.

Configuring for Android and iOS

For an Android emulator (such as a simulated Samsung Galaxy A40), you specify the platform data, the device name, and the UDID. Additionally, Android requires either a path to your APK file via the "app" property, or two specific properties that define the app package and the app starting activity (as defined in your AndroidManifest.xml).

With iOS, physical devices must first be provisioned. In the JSON configuration, you use specific properties for this, such as xcodeOrgId and xcodeSigningId. Instead of the bundleId, you can also use the "app" property here to point directly to an IPA file. A typical configuration looks like this:

JSON

{
 "appium:platformName": "Android",
 "appium:platformVersion": "11",
 "appium:deviceName": "Samsung Galaxy A40",
 "appium:udid": "******",
 "appium:appPackage": "com.coffeeit.appium_example",
 "appium:appActivity": "com.coffeeit.appium_example.MainActivity",
 "appium:noReset": "false",
 "appium:fullReset": "false"
}

What do "noReset" and "fullReset" do?

Beginning Appium users often get confused by the "noReset" and "fullReset" keys. These properties instruct Appium to either clear the app data or completely uninstall the app before a test starts. This is incredibly useful when you want to repeatedly test an app's onboarding flow from a clean slate, for example.

  • If noReset is set to true, all app data will be cleared
  • If fullReset is set to true, the app will be uninstalled and reinstalled (this is onlypossible if a path to an APK/IPA is provided)

I personally always clear the app data because you can’t rely on the state of an app. Clearing the app data will give a test higher assurance of passing successfully.Accessibility idsWhen writing tests we have to interact with UI elements. There are different methods to dothis. UI elements are identifiable by:

  • Id
  • Accessibility id
  • xpathThe nested path of an element
  • Class nameClass name of the element
  • Tag name
  • And various other Android/iOS related methods

The best way is to use accessibility ids. Simply because accessibility ids do not require codechanges and can be synchronized between multiple apps. So if you have an Android and aniOS app, depending on how much they differ, you will be able to use the same test for bothapps. Meaning you don’t need to create a separate test for Android and a different one foriOS. Furthermore, you can use if conditions in your code to perform iOS only or Android onlyUI operations.

Hier is het laatste deel van je tekst, op precies dezelfde wijze herschreven: compact, scanbaar met overzichtelijke koppen (H2, H3, H4), vetgedrukte kernwoorden en strakke code-blokken.

Writing Tests with Kotlin

Now that we understand Appium’s Desired Capabilities and have a basic understanding of how we can identify UI elements, we can start writing tests. I will be using Kotlin in this blog post.

Step 1: Import Dependencies

First, we need to import a few required dependencies into our project:

Kotlin

dependencies {
   implementation("io.appium:java-client:8.0.0")
   implementation("org.seleniumhq.selenium:selenium-java:4.1.4")
   implementation("org.testng:testng:7.5")
   testImplementation("org.testng:testng:7.5")
}

Step 2: Create the Test Class

For this example, I will be testing a simple tasks app that I created. Create a new class in src/test/kotlin called TodoTasksTest which looks like this:

Kotlin

import io.appium.java_client.AppiumBy
import io.appium.java_client.android.AndroidDriver
import org.openqa.selenium.WebDriver
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.support.ui.ExpectedConditions
import org.openqa.selenium.support.ui.WebDriverWait
import org.testng.annotations.AfterTest
import org.testng.annotations.BeforeTest
import org.testng.annotations.Test
import java.net.URL
import java.time.Duration

class TodoTasksTest {
   private lateinit var driver: WebDriver
   private lateinit var waiter: WebDriverWait

   @BeforeTest
   fun setup() {
       // Setup the desired capabilities
       val capabilities = DesiredCapabilities()
       capabilities.setCapability("platformName", "Android")
       capabilities.setCapability("deviceName", "Samsung Galaxy A40")
       capabilities.setCapability("platformVersion", "11")
       capabilities.setCapability("udid", "******")
       capabilities.setCapability("appPackage", "com.coffeeit.appium_example")
       capabilities.setCapability("appActivity", "com.coffeeit.appium_example.MainActivity")
       capabilities.setCapability("noReset", "false")
       capabilities.setCapability("fullReset", "false")

       driver = AndroidDriver(URL("http://127.0.0.1:4723/wd/hub"), capabilities)
       waiter = WebDriverWait(driver, Duration.ofSeconds(10L))
   }

   @Test
   fun testAddTask() {
       // wait for the element to be visible and click on it
       waiter.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId("AddTask"))).click()

       // if accessibility ids are not defined, we can identify elements in different ways
       val elements = driver.findElements(AppiumBy.className("android.widget.EditText"))
       elements[0].sendKeys("Some title")
       elements[1].sendKeys("Some description")

       // wait for the element to be visible and click on it
       waiter.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId("SaveTask"))).click()
   }

   @Test
   fun testAddTaskBackButton() {
       // wait for the element to be visible and click on it
       waiter.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId("AddTask"))).click()

       // wait for the element to be visible and click on it
       waiter.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId("Back"))).click()
   }

   @AfterTest
   fun teardown() {
       driver.quit()
   }
}

In the example above, we start by setting up our capabilities. After that, two tests are defined: one adds a new task with a title and description, while the other presses the back button when trying to add a task. In the final function, we terminate the automation session.

The longest step here is setting up the capabilities and preparing the test device. The tests themselves take just a few seconds.

Next time we want to test something, we simply start the Appium server, connect our device, and run our tests. However, what if you are not a developer? Can you still use Appium to write tests?

Introduction to TestProject

Appium is a free, open-source framework designed to automate testing as much as possible, and it does a pretty good job. However, you still need to be a developer to write tests.

Fortunately, commercial test automation frameworks offer online environments where you can test apps without writing code. You can set up test data, record tests, and integrate them into cloud solutions like GitLab CI or AWS.

In 2015, an open-source effort started to provide these premium features to the world for free. In April 2018, the first version of this online test environment was released under the name TestProject.

TestProject is a free, end-to-end test automation platform for web, mobile, and API testing that makes great use of Appium. It is a highly powerful platform that can be used completely free of charge.

Important Core Considerations

While TestProject claims to be open-source, only their SDK and plugins actually are. The online environment itself is closed-source. This means you cannot run a local instance of the online dashboard, and an active internet connection is mandatory to use it.

How to Use TestProject

Using TestProject is very straightforward:

  1. Register an account and log in.
  2. Follow the setup wizard and confirm your email.
  3. Set up the TestProject Agent. This agent runs an Appium server in the background and interacts directly with your test devices and emulators.

Once configured, you will land in the test environment where a default test project is automatically created to get you started.

Navigating the TestProject Dashboard

At the top left of the dashboard, you can see your current project and switch to others. The tabs below it handle your project-specific data:

Tests & Jobs

TestProject splits work into tests and jobs. Tests simply follow a specific flow of steps, while jobs are one or multiple tests attached to a specific device. Jobs can be triggered manually or scheduled.

Elements

In the Elements tab, you can pre-define UI elements. Pre-defining elements makes writing multiple tests much easier because you can simply reference them later without rewriting code.

Applications & Data Sources

  • Applications: Define the specific apps you want to test.
  • Data Sources: Store external files (like a CSV file) to pave the way for Data-Driven Tests and Jobs.

Parameters & Devices

  • Parameters: Define project-level key/value parameters (like login credentials) to reuse them across tests.
  • Devices: Authorize your testing hardware. When the agent recognizes a new device, a authorization popup will appear.

Advanced Test & Step Configuration

When you open a test, all related information is displayed. You can record steps natively (which requires a local TestProject agent to be running) or create steps manually.

Global vs. Step-Level Settings

The gear icon at the top left exposes the global test settings. Here, you can configure:

  • How fast the test should execute.
  • What happens if a step fails.
  • Whether screenshots should be taken at each step.

While these apply globally, TestProject also allows you to override these rules on a step-level basis by expanding the advanced options inside any individual step.

Inside the Steps Tab

Each step in a test has a specific action that needs to be performed. TestProject offers a wide range of built-in options and supports Add-ons.

Add-ons are incredibly useful when you need to interact with native UI elements outside of your app, and they can be created and shared by anyone in the community.

Platform Reports and Integrations

Beautiful Reporting

TestProject can automatically generate beautiful, detailed test reports. These explain the test execution from start to finish, highlighting the exact test data used and actions performed.

Summary and full reports can easily be shared with stakeholders. If your test is configured to take screenshots at every step, those images will be directly linked inside the full report.

Third-Party Integrations

TestProject integrates natively with platforms like Sauce Labs and BrowserStack, and supports custom webhooks for success/failure notifications.

While TestProject agents can run inside Docker containers, note that Docker-based agents do not currently support local hardware device recognition.

API & GitLab CI Pipelines

TestProject features a massive API that allows you to easily trigger tests and jobs remotely. For example, you can write your own custom integration pipeline in GitLab CI for Android testing. This sequence executes a series of jobs and only exits the pipeline when all tasks pass successfully:

YAML

# Minimal OS image with Java and Android 31 build tools pre-installed
image: mreichelt/android:31

variables:
 # Colors for terminal output
 Color_Off: '\e[0m'
 Red: '\e[0;31m'
 Green: '\e[0;32m'
 BRed: '\e[1;31m'
 BGreen: '\e[1;32m'
 BBlue: '\e[1;34m'
 
 # TestProject variables
 TP_API_URL: "https://api.testproject.io/v2"
 TEST_RETRIES: 2
 TP_API_KEY: "SOME_API_KEY"
 TP_PROJECT_ID: "some_project_id"
 TP_APP_ID: "some_app_id"
 TP_APK_FILE_NAME: "app-debug.apk"
 TP_JOBS: "job_id_1 job_id_2"

before_script:
 - apt-get --quiet update --yes
 - apt-get --quiet install jq --yes

stages:
 - build
 - upload
 - test

# Build project
assembleDebug:
 interruptible: true
 stage: build
 script:
   - ./gradlew -Dorg.gradle.jvmargs=-Xmx2048m assembleDebug
 artifacts:
   untracked: true
   paths:
     - app/build/outputs/

# Upload the APK to TestProject
uploadAPK:
 interruptible: true
 stage: upload
 script:
   # Get AWS url from TestProject to upload to
   - 'UPLOAD_DATA=$(curl -s -S -X GET "${TP_API_URL}/projects/${TP_PROJECT_ID}/applications/${TP_APP_ID}/file/upload-link" -H "accept: application/json" -H "Authorization: ${TP_API_KEY}")'
   - echo $UPLOAD_DATA
   # Parse the upload url
   - UPLOAD_URL=$(echo $UPLOAD_DATA | jq -r ".url")
   - UPLOAD_METHOD=$(echo $UPLOAD_DATA | jq -r ".method.Method")
   - echo $UPLOAD_URL
   - echo $UPLOAD_METHOD
   # Upload the APK to the upload url
   - curl "${UPLOAD_URL}" --upload-file app/build/outputs/apk/debug/app-debug.apk
   # Publish the APK to the TestProject app
   - 'UPLOAD_CONFIRM_DATA=$(curl -X POST "${TP_API_URL}/projects/${TP_PROJECT_ID}/applications/${TP_APP_ID}/file" -H "accept: application/json" -H "Authorization: ${TP_API_KEY}" -H "Content-Type: application/json" -d "{ \"fileName\": \"${TP_APK_FILE_NAME}\" }")'

Yassin Amhagi

Veelgestelde vragen

Wat is Appium en waarvoor wordt het gebruikt?

Appium is een open source testautomatiseringsframework voor mobiele apps. Het ondersteunt native, hybride en mobiele webapps en maakt het mogelijk om geautomatiseerde tests te schrijven voor zowel Android als iOS.

Welke programmeertalen kun je gebruiken met Appium?

Met Appium kun je tests schrijven in verschillende programmeertalen zoals Java, Kotlin, JavaScript, Python, Ruby en C#. Dit gebeurt via de Selenium WebDriver API en bijbehorende client libraries.

Wat zijn Desired Capabilities in Appium?

Desired Capabilities zijn configuratie-instellingen die je naar de Appium-server stuurt bij het starten van een testsessie. Hierin geef je onder andere aan welk apparaat, besturingssysteem en welke app getest moet worden.

Waarom zijn accessibility ID’s belangrijk bij het schrijven van mobiele tests?

Accessibility ID’s maken het mogelijk om UI-elementen stabiel en platformonafhankelijk te identificeren. Hierdoor kun je vaak dezelfde test gebruiken voor zowel Android als iOS, wat onderhoud en ontwikkeling efficiënter maakt.

Wat is het verschil tussen Appium en TestProject?

Appium vereist programmeerkennis om tests te schrijven en te beheren. TestProject bouwt voort op Appium en biedt een gebruiksvriendelijke online omgeving waarmee ook niet-developers geautomatiseerde tests kunnen opzetten, beheren en rapporteren.

Gerelateerde blogs