You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 06:36:11