Appium Android Automation Test Setup

TL;DR: Complete guide for setting up Appium mobile automation testing infrastructure on Ubuntu servers

Overview

Set up a complete Appium-based mobile automation testing environment on Ubuntu servers for Android application testing.

Prerequisites Installation

Node.js via NVM

# Install NVM
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash

# Load NVM
source ~/.profile

# Install Node.js LTS
nvm install 16

Appium Installation

# Install Appium
npm install -g appium@1.21.0

# Install Appium Doctor for verification
npm install appium-doctor -g

# Verify installation
appium-doctor --android

Android SDK

# Install Android SDK
sudo apt update && sudo apt install android-sdk

# SDK installed at: /usr/lib/android-sdk

# Install graphics libraries for emulator
sudo apt-get install libgl1-mesa-dev

Android Emulator Setup

# Download SDK tools
wget https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
tar -xvf android-sdk_r24.4.1-linux.tgz

# Download build-tools (version 29.0.0 for Android 10)
# Copy build-tools into platform-tools directory
cp -r ./build-tools/. /opt/android-sdk/platform-tools/

Environment Variables

# Add to ~/.bashrc or ~/.profile
export ANDROID_HOME=/opt/android-sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/emulator
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

Creating Android Emulator

Android 10 (API 29) Emulator

# Download system image
/opt/android-sdk/tools/bin/sdkmanager \
  "system-images;android-29;google_apis;x86_64"

# Create AVD
/opt/android-sdk/tools/bin/avdmanager -v create avd \
  -f \
  -n TestAVD \
  -k "system-images;android-29;google_apis;x86_64" \
  -p "/opt/android-sdk/avd"

# Start emulator (headless for CI)
/opt/android-sdk/emulator/emulator \
  -port 5556 \
  -avd TestAVD \
  -no-window \
  -memory 2048 \
  -no-audio \
  -gpu swiftshader_indirect \
  -show-kernel \
  -no-accel

Alternative Android Versions

# Android 8 (API 26) for ARM devices
sdkmanager "system-images;android-26;google_apis;arm64-v8a"

avdmanager -v create avd \
  -f \
  -n TestAVD26 \
  -k "system-images;android-26;google_apis;arm64-v8a" \
  -p "/opt/android-sdk/avd"

ADB Commands Reference

Device Management

# List connected devices
adb devices

# Connect to specific emulator
adb -s emulator-5556 shell

# Get Android version
adb shell getprop ro.build.version.release

# Get API level
adb shell getprop ro.build.version.sdk

# List all system properties
adb shell getprop

App Management

# Install APK
adb -s emulator-5556 install -r ~/apps/test-app-debug.apk

# Uninstall app
adb -s emulator-5556 uninstall com.example.testapp

# List installed packages
adb -s emulator-5556 shell pm list packages

# Find specific package
adb shell pm list packages com.example

# Start app activity
adb shell am start -n com.example.testapp/.MainActivity

Appium Test Configuration

Desired Capabilities

// TestConfig.java
public class TestConfig {
    
    public static DesiredCapabilities getCapabilities() {
        DesiredCapabilities caps = new DesiredCapabilities();
        
        caps.setCapability("platformName", "Android");
        caps.setCapability("platformVersion", "10");
        caps.setCapability("deviceName", "emulator-5556");
        caps.setCapability("automationName", "UiAutomator2");
        caps.setCapability("app", "/path/to/app-debug.apk");
        caps.setCapability("appPackage", "com.example.testapp");
        caps.setCapability("appActivity", ".MainActivity");
        caps.setCapability("noReset", false);
        caps.setCapability("fullReset", false);
        
        return caps;
    }
}

Test Runner Setup

// BaseTest.java
public class BaseTest {
    protected AndroidDriver<MobileElement> driver;
    
    @BeforeClass
    public void setUp() throws MalformedURLException {
        DesiredCapabilities caps = TestConfig.getCapabilities();
        driver = new AndroidDriver<>(
            new URL("http://localhost:4723/wd/hub"),
            caps
        );
        driver.manage().timeouts()
            .implicitlyWait(30, TimeUnit.SECONDS);
    }
    
    @AfterClass
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

Running Tests

Start Appium Server

# Start Appium
appium -p 4723 -a 127.0.0.1

# Or with logging
appium -p 4723 -a 127.0.0.1 --log /var/log/appium.log

Execute Test Suite

# Run fat JAR with TestNG XML
java -jar target/automation-tests-fat.jar test_suite.xml

# Run specific test class
java -jar target/automation-tests-fat.jar \
  -testclass com.example.tests.LoginTest

CI/CD Integration

File Transfer to Server

# Copy APK to server
scp -i ~/keys/server.pem \
  ~/builds/app-debug.apk \
  ubuntu@172.xx.xx.xx:~/apps/

# Copy test JAR to server
scp -r -i ~/keys/server.pem \
  ~/project/target \
  ubuntu@172.xx.xx.xx:~/workspace/automation

Jenkins Pipeline

// Jenkinsfile
pipeline {
    agent any
    
    stages {
        stage('Setup Emulator') {
            steps {
                sh '''
                    # Start emulator in background
                    nohup emulator -port 5554 -avd TestAVD \
                      -no-window -no-audio \
                      -gpu swiftshader_indirect &
                    
                    # Wait for emulator to boot
                    adb wait-for-device
                    sleep 30
                '''
            }
        }
        
        stage('Install App') {
            steps {
                sh '''
                    adb -s emulator-5554 install -r \
                      ${WORKSPACE}/app-debug.apk
                '''
            }
        }
        
        stage('Run Tests') {
            steps {
                sh '''
                    appium &
                    sleep 10
                    
                    java -jar target/automation-fat.jar \
                      test_suite.xml
                '''
            }
        }
    }
    
    post {
        always {
            sh 'adb -s emulator-5554 emu kill || true'
            sh 'pkill -f appium || true'
        }
    }
}

Troubleshooting

UIAutomator2 Server Error

# Error: App not installed
# Solution: Install UIAutomator2 server APK manually
adb install ~/.nvm/versions/node/v16.x/lib/node_modules/appium/\
node_modules/appium-uiautomator2-server/apks/\
appium-uiautomator2-server-v4.21.1.apk

Permission Issues

# zipAlign EACCES error
chmod 777 /opt/android-sdk
chmod 777 /opt/android-sdk/platform-tools/zipalign

Emulator Process Management

# Check running emulator processes
ps -ef | grep emulator

# Kill specific process
kill <processId>

# Kill all emulator processes
pkill -f emulator

Best Practices

  1. Use headless emulators for CI environments
  2. Set reasonable timeouts to avoid flaky tests
  3. Clear app data between test runs when needed
  4. Use explicit waits instead of implicit waits
  5. Capture screenshots on test failures
  6. Run tests in parallel on multiple emulators