1. 移动端与Web端自动化测试框架联动方案概述
在当今多端融合的测试场景中,经常需要验证移动端App与Web端业务系统的数据一致性或流程连贯性。传统测试方案往往需要分别执行移动端和Web端测试用例,无法实现真正的端到端验证。uiautomator2作为Android平台主流自动化测试框架,与Selenium Web自动化测试框架的联动,为解决这一难题提供了技术可能性。
这种联动测试方案的核心价值在于:
- 实现真正的跨平台业务流程验证(如App下单→Web后台审核)
- 共享测试数据与状态,避免人工同步
- 统一测试报告生成与分析
- 降低多团队协作的沟通成本
2. 环境搭建与框架集成
2.1 基础环境准备
联动测试需要同时配置移动端和Web端测试环境:
# Python环境(建议3.7+) pip install uiautomator2 selenium webdriver-manager # 初始化uiautomator2 python -m uiautomator2 init2.2 设备连接配置
移动端设备连接支持USB和Wi-Fi两种模式:
import uiautomator2 as u2 # USB连接(需先启用开发者模式) d = u2.connect('设备序列号') # WiFi连接(需同局域网) d = u2.connect('192.168.1.100:5555') # WebDriver配置(以Chrome为例) from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager driver = webdriver.Chrome(ChromeDriverManager().install())2.3 跨框架会话管理
建议使用pytest的fixture管理测试会话:
import pytest @pytest.fixture(scope='session') def mobile_driver(): d = u2.connect() yield d d.app_stop_all() @pytest.fixture(scope='function') def web_driver(): driver = webdriver.Chrome() yield driver driver.quit()3. 核心联动技术实现
3.1 状态共享机制
实现框架间状态传递的三种方案:
- 文件共享(适合简单数据)
# 移动端保存数据 d(resourceId="com.example:id/tv_order").screenshot('order.png') # Web端读取使用 driver.find_element(By.NAME, 'order_input').send_keys( pytesseract.image_to_string('order.png'))- 内存数据库(适合复杂场景)
# 共用Redis实例 import redis r = redis.Redis() # 移动端存储 order_id = d(resourceId="com.example:id/order_id").get_text() r.set('current_order', order_id) # Web端读取 driver.get(f"https://admin.example.com/orders/{r.get('current_order')}")- API中间层(企业级方案)
# 通过内部接口服务交换数据 import requests # App获取令牌 token = d(resourceId="com.example:id/token").get_text() requests.post('http://internal-api/tokens', json={'token': token}) # Web使用令牌 driver.add_cookie({ 'name': 'auth_token', 'value': requests.get('http://internal-api/tokens').json()['token'] })3.2 元素定位策略对比
| 定位方式 | uiautomator2示例 | Selenium示例 | 适用场景 |
|---|---|---|---|
| ID定位 | d(resourceId="com.example:id/btn") | driver.find_element(By.ID, "btn") | 首选方式 |
| 文本定位 | d(text="登录") | driver.find_element(By.LINK_TEXT, "登录") | 静态文本元素 |
| XPath | d.xpath('//*[@text="提交"]') | driver.find_element(By.XPATH, '//button') | 复杂层级结构 |
| 类名定位 | d(className="android.widget.EditText") | driver.find_element(By.CLASS_NAME, "form-control") | 标准组件 |
3.3 等待机制同步
处理不同平台的加载差异:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def wait_both_ready(mobile_element, web_element, timeout=30): # 移动端等待 if not mobile_element.wait(timeout=timeout/1000): raise TimeoutError("移动端元素未加载") # Web端等待 WebDriverWait(driver, timeout).until( EC.visibility_of_element_located(web_element) )4. 典型联动测试场景实现
4.1 跨端数据验证测试
验证App提交的数据在Web后台正确显示:
def test_order_sync(mobile_driver, web_driver): # 在App下单 mobile_driver(resourceId="com.shop:id/btn_order").click() order_id = mobile_driver(resourceId="com.shop:id/order_id").get_text() # 在Web后台查询 web_driver.get("http://admin.shop.com/orders") web_driver.find_element(By.ID, "search_input").send_keys(order_id) assert order_id in web_driver.page_source4.2 连续业务流程测试
App到Web的完整业务流程验证:
def test_cross_platform_flow(): # 阶段1:App端操作 d(resourceId="com.app:id/start_btn").click() d(text="立即购买").click() # 阶段2:Web支付验证 driver.get("http://pay.example.com") qr_code = d(resourceId="com.app:id/qrcode").get_text() driver.find_element(By.NAME, "payment_code").send_keys(qr_code) assert "支付成功" in driver.page_source # 阶段3:App状态确认 assert d(text="支付完成").exists4.3 性能对比测试
import time def test_performance_comparison(): # App端操作耗时 start = time.time() d(text="刷新").click() d(text="最新数据").wait() app_duration = time.time() - start # Web端相同操作 start = time.time() driver.find_element(By.LINK_TEXT, "刷新").click() WebDriverWait(driver, 10).until( EC.text_to_be_present_in_element((By.TAG_NAME, "body"), "最新数据") ) web_duration = time.time() - start assert abs(app_duration - web_duration) < 3 # 允许3秒差异5. 常见问题与解决方案
5.1 设备兼容性问题
现象:不同Android版本元素属性差异
解决方案:
# 使用多重定位策略 element = (d(text="提交") or d(description="提交按钮") or d.xpath('//*[contains(@text, "提交")]')) element.click()5.2 网络切换处理
场景:App操作后需要切换网络环境访问Web
处理方案:
def switch_network(driver): driver.reset() # 清除Web端缓存 # 实际项目中可以调用企业内部的网络切换API # requests.post('http://network-api/switch', json={'type':'wifi'})5.3 验证码处理
联动测试中的验证码破解方案:
def handle_captcha(): # 方案1:测试环境禁用验证码 if is_test_env: return # 方案2:OCR识别(需安装tesseract) captcha_img = d(resourceId="com.app:id/captcha").screenshot() captcha = pytesseract.image_to_string(captcha_img) driver.find_element(By.NAME, "captcha").send_keys(captcha) # 方案3:后端接口获取(需开发配合) # captcha = requests.get('http://dev-api/captcha').text6. 测试报告与持续集成
6.1 统一报告生成
使用Allure整合两个框架的测试结果:
import allure @allure.step("移动端登录操作") def app_login(): d(resourceId="com.app:id/username").set_text("testuser") d(resourceId="com.app:id/password").set_text("pass123") d(resourceId="com.app:id/login_btn").click() @allure.step("Web端验证登录状态") def web_verify_login(): driver.get("http://admin.example.com") assert "testuser" in driver.page_source6.2 Jenkins集成配置
示例流水线脚本:
pipeline { agent any stages { stage('Test') { steps { sh 'python -m pytest tests/ --alluredir=./allure-results' } } } post { always { allure includeProperties: false, jdk: '', results: [[path: 'allure-results']] } } }7. 性能优化建议
- 会话复用:保持WebDriver和uiautomator2会话长期存活
- 并行执行:使用pytest-xdist并行运行独立测试用例
- 智能等待:根据网络状况动态调整等待超时
- 元素缓存:对高频访问元素进行对象缓存
- 图片优化:压缩截图图片分辨率(示例代码):
def optimized_screenshot(d, element): original = element.screenshot(format='opencv') # 压缩到50%质量 return cv2.imencode('.jpg', original, [cv2.IMWRITE_JPEG_QUALITY, 50])[1]在实际企业级测试体系中,这种联动方案可以将端到端测试效率提升40%以上,同时显著降低不同团队间的协作成本。关键在于建立统一的测试数据管理体系和标准的元素定位规范。