基于Appium实现多模拟器并发会话的可行性与方案咨询
可行性分析
Appium基于WebDriver协议,每个模拟器/设备对应独立的Session,结合Android Emulator的多实例能力,完全支持多模拟器并发会话,可满足你提到的多用户交互测试场景(消息、通话等),不存在技术障碍。
实施方案
1. 多Android模拟器实例配置与启动
创建多AVD
通过Android Studio的AVD Manager创建至少2个独立AVD(或同一AVD的不同实例),根据测试需求配置硬件参数。
命令行启动多模拟器
使用emulator命令启动不同端口的模拟器,避免端口冲突:
# 启动第一个模拟器,端口5554 emulator -avd Pixel_5_API_33 -port 5554 -no-boot-anim -no-window # 启动第二个模拟器,端口5556 emulator -avd Pixel_4_API_33 -port 5556 -no-boot-anim -no-window
启动后通过adb devices验证设备连接状态:
adb devices # 预期输出: # emulator-5554 device # emulator-5556 device
2. 多Appium服务启动
每个模拟器对应一个独立的Appium服务(推荐此方式避免Session干扰):
本地启动多服务
# 第一个Appium服务,端口4723 appium -p 4723 --session-override # 第二个Appium服务,端口4725 appium -p 4725 --session-override
Docker方式启动多Appium容器
利用Docker隔离实例,需配置网络让容器访问宿主机模拟器:
# 第一个容器,映射宿主机4723端口 docker run -d --network host appium/appium:latest # 第二个容器,指定内部端口为4725并映射到宿主机 docker run -d --network host -e APPIUM_PORT=4725 appium/appium:latest
3. 测试脚本实现(Python示例)
使用多线程管理两个独立的Appium Session,分别处理不同用户的操作:
基础配置
定义两个用户的Desired Capabilities,关联对应模拟器和Appium服务:
from appium import webdriver import threading from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 用户1的Capabilities(对应emulator-5554,连接4723端口服务) caps_user1 = { "platformName": "Android", "deviceName": "Pixel_5_API_33", "udid": "emulator-5554", "appPackage": "com.your.app.package", "appActivity": "com.your.app.MainActivity", "noReset": False, "automationName": "UiAutomator2" } # 用户2的Capabilities(对应emulator-5556,连接4725端口服务) caps_user2 = { "platformName": "Android", "deviceName": "Pixel_4_API_33", "udid": "emulator-5556", "appPackage": "com.your.app.package", "appActivity": "com.your.app.MainActivity", "noReset": False, "automationName": "UiAutomator2" } appium_url_user1 = "http://localhost:4723/wd/hub" appium_url_user2 = "http://localhost:4725/wd/hub"
场景1:消息发送与接收验证
def user1_send_message(): driver = webdriver.Remote(appium_url_user1, caps_user1) # 用户1登录流程(替换为你的实际元素定位) WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "username_input"))).send_keys("user1") driver.find_element(By.ID, "password_input").send_keys("password1") driver.find_element(By.ID, "login_btn").click() # 进入聊天界面发送消息给用户2 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "search_user_input"))).send_keys("user2") driver.find_element(By.ID, "user2_chat_item").click() driver.find_element(By.ID, "message_input").send_keys("Hello from User1!") driver.find_element(By.ID, "send_btn").click() driver.quit() def user2_receive_message(): driver = webdriver.Remote(appium_url_user2, caps_user2) # 用户2登录流程 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "username_input"))).send_keys("user2") driver.find_element(By.ID, "password_input").send_keys("password2") driver.find_element(By.ID, "login_btn").click() # 验证接收消息 message_element = WebDriverWait(driver, 30).until( EC.presence_of_element_located((By.XPATH, "//*[@text='Hello from User1!']")) ) assert message_element.is_displayed(), "用户2未收到消息" driver.quit() # 启动多线程执行 thread1 = threading.Thread(target=user1_send_message) thread2 = threading.Thread(target=user2_receive_message) thread1.start() thread2.start() thread1.join() thread2.join()
场景2:呼叫与接收验证
def user1_initiate_call(): driver = webdriver.Remote(appium_url_user1, caps_user1) # 用户1登录流程 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "username_input"))).send_keys("user1") driver.find_element(By.ID, "password_input").send_keys("password1") driver.find_element(By.ID, "login_btn").click() # 发起呼叫给用户2 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "search_user_input"))).send_keys("user2") driver.find_element(By.ID, "user2_profile").click() driver.find_element(By.ID, "call_btn").click() # 等待5秒后结束呼叫 import time time.sleep(5) driver.find_element(By.ID, "end_call_btn").click() driver.quit() def user2_accept_call(): driver = webdriver.Remote(appium_url_user2, caps_user2) # 用户2登录流程 WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, "username_input"))).send_keys("user2") driver.find_element(By.ID, "password_input").send_keys("password2") driver.find_element(By.ID, "login_btn").click() # 验证并接听呼叫 call_incoming_element = WebDriverWait(driver, 30).until( EC.presence_of_element_located((By.ID, "incoming_call_notification")) ) assert call_incoming_element.is_displayed(), "用户2未收到呼叫" driver.find_element(By.ID, "accept_call_btn").click() # 等待呼叫结束 WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "call_ended_status"))) driver.quit() # 启动多线程执行 thread1 = threading.Thread(target=user1_initiate_call) thread2 = threading.Thread(target=user2_accept_call) thread1.start() thread2.start() thread1.join() thread2.join()
注意事项
- 资源分配:多模拟器实例占用大量CPU和内存,推荐测试机器配置至少8核CPU+16GB内存。
- 同步机制:复杂场景需引入
threading.Event等同步工具,避免操作时序冲突。 - 版本兼容:使用最新稳定版Appium,避免旧版本的并发Session bug。
- Docker网络:必须使用
--network host模式,否则需手动映射adb端口(5554、5556等)。
内容的提问来源于stack exchange,提问作者Surbhi Gupta
相关产品推荐
相关产品推荐

