千锋教育-做有情怀、有良心、有品质的职业教育机构

一个脚本跑通双平台,Appium让移动端测试效率提升80%_千锋教育

来源:千锋教育
发布时间:2026-07-03 18:29:39

千锋教育品牌logo

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种方式

定位策略AndroidiOS推荐场景
IDresource-idaccessibility-id唯一标识
XPath完整XPath完整XPath复杂结构
Class Nameclass属性type属性同类型元素
Accessibility IDcontent-descaccessibility-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%,不是梦,是代码。

声明:本站部分稿件版权来源于网络,如有侵犯版权,请及时联系我们。

学习资源站

  • 免费全套视频教程
  • 企业实战项目源码
  • 大厂笔试真题题库
  • 行业前瞻发展趋势

相关推荐

  • 别人在写用例,你在写专利:测试工程师的退休金藏在代码里_千锋教育 01为什么测试工程师最适合搞专利?因为你的饭碗里藏着金矿测试工程师每天都在做一件事:找茬。但99%的人只找到了Bug,没找到专利。Bug是别人的错误,专利是你的护城河。一个Bug只能填Jira,一个专利能填退休账户。数据不会说谎:2023年
  • 远程测试3大痛点,效率提升200%的破局方案_千锋教育 01沟通断层:远程测试的第一杀手远程办公第一天,测试团队就炸了锅。开发提交了一个新版本,测试人员小王花了3小时搭建环境、执行用例,发现5个严重缺陷。但等他写好缺陷报告,开发已经下班了。第二天开发看到报告,发现其中3个是环境配置问题,1个是旧
  • 测试组长每天少干3小时:不是偷懒,是这5个社区在替他工作_千锋教育 01为什么你的测试团队永远在救火?因为你只盯着Bug大多数测试管理者陷入一个死循环:团队越忙,Bug越多;Bug越多,团队越忙。这不是能力问题,是认知问题。你花在社区上的每一分钟,都在为团队节省10小时。我见过一个测试组长,每天花15分钟浏
  • 接口测试进阶:文件上传接口的3个死穴,95%的测试都踩过_千锋教育 01文件上传接口的“隐形杀手”:JS渲染与异步加载文件上传接口测试,看似简单:构造请求,发送文件,验证响应。但现实给了你一巴掌——脚本运行时,页面元素还没加载完,文件选择对话框弹不出来,上传进度条卡住不动,断言结果永远失败。问题出在哪?现代
  • 一个脚本跑通双平台,Appium让移动端测试效率提升80%_千锋教育 01为什么Appium是移动测试的第一选择移动端测试,曾经是测试工程师的噩梦。Android用UIAutomator,iOS用XCUITest,两套技术栈,两套脚本,维护成本翻倍。项目迭代快,版本更新频繁,测试脚本跟不上开发速度,测试人员疲
  • 3个月从零到行业大会演讲嘉宾:测试工程师的社交媒体运营秘籍_千锋教育 01为什么测试工程师必须运营社交媒体?——职业杠杆的底层逻辑测试工程师的晋升路径,从来不是靠默默写用例。行业里,80%的测试专家在35岁前完成向技术管理或高级顾问的转型,靠的不是代码量,是影响力。LinkedIn、Twitter、知乎,这三