01 为什么Appium是移动测试的第一选择
移动端测试,曾经是测试工程师的噩梦。Android用UIAutomator,iOS用XCUITest,两套技术栈,两套脚本,维护成本翻倍。项目迭代快,版本更新频繁,测试脚本跟不上开发速度,测试人员疲于奔命。

Appium打破了这种局面。它基于WebDriver协议,用一套API操作双平台。一次编写,Android和iOS同时运行。测试脚本维护成本降低60%,执行效率提升80%。
一个框架统治双平台,这才是真正的效率。
Appium的核心优势在于:
- ►跨平台:同一套代码,同时支持Android和iOS
- ►多语言:Java、Python、JavaScript、Ruby,你想用什么就用什么
- ►无需源码:不需要App源代码,直接测试安装包
- ►原生支持:原生应用、Hybrid应用、Web应用全覆盖
数据说话:采用Appium的企业,测试脚本开发周期缩短45%,回归测试时间减少70%。一个测试人员可以覆盖之前3个人的工作量。
02 环境搭建:5分钟搞定双平台配置
环境搭建是Appium入门的第一道坎。很多人卡在这里,因为需要配置的东西太多。按照下面的步骤,5分钟搞定。
安装Appium Server
bash
# 使用npm安装
npm install -g appium
# 验证安装
appium --version
# 输出: 2.5.1
安装Appium Inspector
Appium Inspector是可视化元素定位工具,下载安装包即可。下载地址:https://github.com/appium/appium-inspector/releases
配置Android环境
bash
# 安装Java JDK 11+
# 安装Android SDK
# 配置环境变量
export ANDROID_HOME=/usr/local/android-sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools
# 验证
adb --version
# 输出: Android Debug Bridge version 1.0.41
配置iOS环境
bash
# 安装Xcode (macOS only)
# 安装Carthage
brew install carthage
# 安装WebDriverAgent
git clone https://github.com/appium/WebDriverAgent.git
cd WebDriverAgent
./Scripts/bootstrap.sh
环境配不好,测试跑不了。5分钟的事,别拖成5小时。
启动Appium Server
bash
# 默认端口4723
appium
# 指定端口
appium -p 4723
03 第一个测试脚本:从启动应用到元素点击
理论说再多,不如动手跑一个脚本。下面用Python编写,同时支持Android和iOS。
安装Appium Python客户端
bash
pip install Appium-Python-Client
编写Android测试脚本
python
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import time
# Android设备配置
desired_caps = {
"platformName": "Android",
"platformVersion": "12.0",
"deviceName": "Android Emulator",
"app": "/path/to/your/app.apk",
"appPackage": "com.example.app",
"appActivity": ".MainActivity",
"noReset": True
}
# 连接Appium Server
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 等待应用启动
time.sleep(5)
# 定位元素并点击
# 使用ID定位
login_button = driver.find_element(AppiumBy.ID, "com.example.app:id/login_btn")
login_button.click()
# 使用XPath定位
username_input = driver.find_element(AppiumBy.XPATH, "//android.widget.EditText[@content-desc='username']")
username_input.send_keys("test_user")
# 断言
assert driver.find_element(AppiumBy.ID, "com.example.app:id/welcome_text").text == "欢迎回来"
# 关闭连接
driver.quit()
编写iOS测试脚本
python
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import time
# iOS设备配置
desired_caps = {
"platformName": "iOS",
"platformVersion": "15.0",
"deviceName": "iPhone 13",
"app": "/path/to/your/app.app",
"automationName": "XCUITest",
"bundleId": "com.example.app",
"noReset": True
}
# 连接Appium Server
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 等待应用启动
time.sleep(5)
# 定位元素并点击
# 使用Accessibility ID定位
login_button = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "loginButton")
login_button.click()
# 使用XPath定位
username_input = driver.find_element(AppiumBy.XPATH, "//XCUIElementTypeTextField[@name='username']")
username_input.send_keys("test_user")
# 断言
assert driver.find_element(AppiumBy.ACCESSIBILITY_ID, "welcomeLabel").label == "欢迎回来"
# 关闭连接
driver.quit()
双平台统一脚本
python
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import time
class MobileTest:
def __init__(self, platform):
self.platform = platform
if platform == "android":
desired_caps = {
"platformName": "Android",
"platformVersion": "12.0",
"deviceName": "Android Emulator",
"app": "/path/to/app.apk",
"appPackage": "com.example.app",
"appActivity": ".MainActivity"
}
else:
desired_caps = {
"platformName": "iOS",
"platformVersion": "15.0",
"deviceName": "iPhone 13",
"app": "/path/to/app.app",
"automationName": "XCUITest"
}
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def login(self, username, password):
# 统一的方法,内部根据平台选择不同的定位策略
if self.platform == "android":
username_el = self.driver.find_element(AppiumBy.ID, "com.example.app:id/username")
else:
username_el = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "usernameField")
username_el.send_keys(username)
if self.platform == "android":
password_el = self.driver.find_element(AppiumBy.ID, "com.example.app:id/password")
else:
password_el = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "passwordField")
password_el.send_keys(password)
if self.platform == "android":
login_btn = self.driver.find_element(AppiumBy.ID, "com.example.app:id/login")
else:
login_btn = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "loginButton")
login_btn.click()
def close(self):
self.driver.quit()
# 使用示例
test = MobileTest("android")
test.login("test_user", "123456")
test.close()
写一次,跑两遍。双平台测试,就是这么简单。
04 实战技巧:元素定位与等待策略
元素定位的5种方式
| 定位策略 | Android | iOS | 推荐场景 |
| ID | resource-id | accessibility-id | 唯一标识 |
| XPath | 完整XPath | 完整XPath | 复杂结构 |
| Class Name | class属性 | type属性 | 同类型元素 |
| Accessibility ID | content-desc | accessibility-label | 可访问性 |
| CSS Selector | 不支持 | 支持 | WebView |
显式等待 vs 隐式等待
python
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 隐式等待(不推荐)
driver.implicitly_wait(10)
# 显式等待(推荐)
wait = WebDriverWait(driver, 10)
element = wait.until(
EC.presence_of_element_located((AppiumBy.ID, "com.example.app:id/login"))
)
element.click()
# 自定义等待条件
def wait_for_element_text(driver, locator, expected_text, timeout=10):
wait = WebDriverWait(driver, timeout)
element = wait.until(
lambda d: d.find_element(*locator).text == expected_text
)
return element
# 使用
locator = (AppiumBy.ID, "com.example.app:id/welcome_text")
element = wait_for_element_text(driver, locator, "欢迎回来")
滑动操作
python
from appium.webdriver.common.touch_action import TouchAction
# 滑动屏幕
def swipe_screen(driver, start_x, start_y, end_x, end_y, duration=800):
action = TouchAction(driver)
action.press(x=start_x, y=start_y).wait(ms=duration).move_to(x=end_x, y=end_y).release()
action.perform()
# 向上滑动
screen_size = driver.get_window_size()
width = screen_size['width']
height = screen_size['height']
swipe_screen(driver, width/2, height*3/4, width/2, height/4)
# 向左滑动
swipe_screen(driver, width*3/4, height/2, width/4, height/2)
等待是门艺术,显式等待是技术。别让隐式等待毁了你的测试。
05 持续集成:让测试自动运行
集成Jenkins
groovy
pipeline {
agent any
stages {
stage('Setup') {
steps {
sh 'npm install -g appium'
sh 'pip install Appium-Python-Client'
}
}
stage('Start Appium') {
steps {
sh 'appium -p 4723 &'
sleep 5
}
}
stage('Run Tests') {
steps {
sh 'pytest tests/ -v --junitxml=report.xml'
}
}
stage('Generate Report') {
steps {
junit 'report.xml'
}
}
stage('Cleanup') {
steps {
sh 'pkill -f appium'
}
}
}
}
并行执行双平台
python
import threading
from appium import webdriver
def run_test_on_platform(platform):
# 配置和测试代码
print(f"Running test on {platform}")
# 实际测试代码
# 创建两个线程并行执行
android_thread = threading.Thread(target=run_test_on_platform, args=("android",))
ios_thread = threading.Thread(target=run_test_on_platform, args=("ios",))
android_thread.start()
ios_thread.start()
android_thread.join()
ios_thread.join()
print("双平台测试完成")
测试报告生成
python
import pytest
import os
# pytest.ini 配置
"""
[pytest]
addopts = -v --html=report.html --self-contained-html
testpaths = tests
python_files = test_*.py
"""
# 运行测试
if __name__ == "__main__":
# 生成HTML报告
pytest.main(["-v", "--html=report.html", "--self-contained-html", "tests/"])
# 发送报告邮件
# 使用smtplib发送邮件
测试不集成,等于白测试。自动化不做CI,效率减一半。
---
Appium不是魔法,是工具。工具的价值在于用它解决问题,而不是研究工具本身。
现在,打开你的终端,装好Appium,跑通第一个测试脚本。从今天开始,你的移动端测试效率提升80%,不是梦,是代码。
声明:本站部分稿件版权来源于网络,如有侵犯版权,请及时联系我们。