Appium并发测试

启动多个Appium服务

Appium常用参数

参数默认值含义
-u, --udidnull连接设备的唯一设备标识符
-a, --address0.0.0.0监听的ip地址
-p, --port4723监听的端口 ,(设置监听端口号时最好间隔一位设置,例如设置下一个端口号设置为4725)
-bp, --bootstrap-port4724连接Android设备的端口号(Android-only)(设备端口号与监听端口号相隔一位)
-g, --lognull将日志输出到指定文件
–no-resetfalsesession之间不重置应用状态
–session-overridefalse允许session被覆盖(冲突的话)
–app-activitynull打开Android应用时,启动的Activity(Android-only)的名字
–appnull本地绝对路径或http URL所指向的一个安装包

更多参数可以输入命令(CMD):appium -h

启动两个appium服务案例

启动第一个appium服务

C:\Users\Administrator>appium -p 4723
[Appium] Welcome to Appium v1.16.0
[Appium] Appium REST http interface listener started on 0.0.0.0:4723

启动第二个appium服务

C:\Users\Administrator>appium -p 4725
[Appium] Welcome to Appium v1.16.0
[Appium] Non-default server args:
[Appium]   port: 4725
[Appium] Appium REST http interface listener started on 0.0.0.0:4725

Appium安卓手机每次运行时都要安装Unlock、Setting解决方案

首先通过如下命令找到appium的安装路径

C:\Users\Administrator>where appium
C:\Users\Administrator\AppData\Roaming\npm\appium
C:\Users\Administrator\AppData\Roaming\npm\appium.cmd

1、打开,并修改以下内容(最好用Notepad++打开)
路径根据上面appium存放文件夹(C:\Users\Shuqing\AppData\Roaming\npm)下继续打开以下相应文件夹
\node_modules\appium\node_modules\appium-android-driver\lib 中的android-helpers.js
修改以下内容(ctrl+g,跳转行快捷键)

#注释475行如下代码(两个斜杠“//”即为注释代码)
//await helpers.pushSettingsApp(adb); 
#注释486行如下代码
//await helpers.pushUnlock(adb);

2.打开C:\Users\Shuqing\AppData\Roaming\npm\node_modules\appium\node_modules\appium-android-driver\build\lib中的android-helpers.js
修改如下内容

#注释1128行下面这行代码
//return _regeneratorRuntime.awrap(helpers.pushSettingsApp(adb));
 #修改为如下:return context$1$0.abrupt('return', defaultIME); 
 #注释1163行下面这行代码
 //return _regeneratorRuntime.awrap(helpers.pushUnlock(adb)); 
 #修改如下:return context$1$0.abrupt('return', defaultIME);

修改完成后重启Appium服务即可,如果新设备没有这个两个守护App可以手动安装这两个App到设备。
Appium Setting路径 :

{appium安装路径}\node_modules\_io.appium.settings@2.4.0@io.appium.settings\app\build\outputs\apk\settings_apk-debug.apk

Unlock app路径:

appium安装路径\node_modules\_appium-unlock@2.0.0@appium-unlock\bin \unlock_apk-debug.apk

启动多台设备

from appium import webdriver
import yaml
from time import ctime
with open("../option_files/Yaml_info.yaml", 'r') as file:
    data = yaml.load(file,Loader=yaml.FullLoader)

def appium_desire(udid,port):
    desired_caps = {}
    desired_caps['platformName'] = data['platformName']
    desired_caps['platformVersion'] = data['platformVersion']
    desired_caps['deviceName'] = data['deviceName']
    desired_caps[udid] = udid
    desired_caps['app'] = data['app']
    desired_caps['noReset'] = data['noReset']
    desired_caps['appPackage'] = data['appPackage']
    desired_caps['appActivity'] = data['appActivity']
    print('appium port:{0} start run devices:{1} at {2}'.format(port, udid, ctime()))
    webdr = webdriver.Remote('http://{0}:{1}/wd/hub'.format(data['ip'],str(port)),desired_caps)
    return webdr
if __name__ == '__main__':
    devices_list = ['127.0.0.1:21503', '127.0.0.1:21513']  #需启动的设备列表
    appium_desire(devices_list[0], 4723)
    appium_desire(devices_list[1], 4725)

capbility配置文件(Yaml_info.yaml)

platformName: Android
platformVersion: 5.1.1
#deviceName: 127.0.0.1:62001
deviceName: 127.0.0.1:21503
#app: D:\Documents\Downloads\com.baidu.BaiduMap.apk
app: D:\Documents\Downloads\com.tencent.mm-7.0.4.apk
noReset: False
#noReset: True
#appPackage: com.baidu.BaiduMap
appPackage: com.tencent.mm
#appActivity: com.baidu.baidumaps.WelcomeScreen
appActivity: com.tencent.mm.ui.LauncherUI
unicodeKeyboard: True
resetKeyboard: True
ip: 127.0.0.1

多进程并发启动设备

from appium import webdriver
import yaml
from time import ctime
import multiprocessing

devices_list = ['127.0.0.1:21503', '127.0.0.1:21513']
with open("../option_files/Yaml_info.yaml", 'r') as file:
    data = yaml.load(file,Loader=yaml.FullLoader)


def appium_desire(udid,port):
    desired_caps = {}
    desired_caps['platformName'] = data['platformName']
    desired_caps['platformVersion'] = data['platformVersion']
    desired_caps['deviceName'] = data['deviceName']
    desired_caps[udid] = udid

    desired_caps['app'] = data['app']
    desired_caps['noReset'] = data['noReset']
    desired_caps['appPackage'] = data['appPackage']
    desired_caps['appActivity'] = data['appActivity']
    print('appium port:{0} start run devices:{1} at {2}'.format(port, udid, ctime()))
    webdr = webdriver.Remote('http://{0}:{1}/wd/hub'.format(data['ip'],str(port)),desired_caps)
    return webdr
# 构造设备进程组
desired_process = []
# 加载进程
for i in range(len(devices_list)):
    port = 4723+2*i
    desired = multiprocessing.Process(target=appium_desire, args=(devices_list[i],port))
    desired_process.append(desired)
    
if __name__ == '__main__':
    # 并发启动多台设备
    for desired in desired_process:
        desired.start()
    for desired in desired_process:
    	desired.join()

Python启动Appium服务

Python启动Appium服务需要使用subprocess模块,该模块可以创建新的进程,并且连接
到进程的输入、输出、错误等广岛信息,并且可以扩区进程的返回值。
subprocess模块官方文档
subprocess.Popen参数参考

启动单个Appium服务

import subprocess
from time import ctime

def appium_start(host,port):
    '''启动appium server'''
    bootstrap_port = str(port+1)
    cmd = "start /b appium -a "+host+' -p '+str(port)+' -bp '+ str(bootstrap_port)   # 其中参数/b 是将cmd窗口指定为后台运行不弹出
    print('{0} at {1}'.format(cmd,ctime()))
    subprocess.Popen(cmd, shell=True, stdout=open('../appium_log/'+str(port)+'.log','a'), stderr=subprocess.STDOUT)

if __name__ == '__main__':
    host = "127.0.0.1"
    port = 4725
    appium_start(host,port)

启动校验

启动后我们需要校验服务是否启动成功,校验方法如下:

  1. 首先查看有没有生成对应的log文件,查看log里面的内容。
  2. 使用如下命令来查看
netstat -ano |findstr 端口号

注:netstat 命令解释
netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。输入 netstat -ano 回车.可以查看本机开放的全部端口;输入命令 netstat -h可以查看全部参数含义。

关闭Appium服务

关闭进程有2种方式,具体如下:

  1. 通过netstat命令找到对应的Appium进程pid然后可以在系统任务管理器去关闭进程;
  2. 使用如下命令来关闭:
taskkill -f -pid appium进程id

多个appium服务启动

import subprocess
from time import ctime

def appium_start(host,port):
    '''启动appium server'''
    bootstrap_port = str(port+1)
    cmd = "start /b appium -a "+host+' -p '+str(port)+' -bp '+ str(bootstrap_port)   # 其中参数/b 是将cmd窗口指定为后台运行不弹出
    print('{0} at {1}'.format(cmd,ctime()))
    subprocess.Popen(cmd, shell=True, stdout=open('../appium_log/'+str(port)+'.log','a'), stderr=subprocess.STDOUT)

if __name__ == '__main__':
    host = "127.0.0.1"
    for i in range(2):
        port = 4723+i*2
        appium_start(host,port)

多进程并发启动appium服务

import subprocess
from time import ctime
from multiprocessing import Process

def appium_start(host,port):
    '''启动appium server'''
    bootstrap_port = str(port+1)
    cmd = "start /b appium -a "+host+' -p '+str(port)+' -bp '+ str(bootstrap_port)   # 其中参数/b 是将cmd窗口指定为后台运行不弹出
    print('{0} at {1}'.format(cmd,ctime()))
    subprocess.Popen(cmd, shell=True, stdout=open('../appium_log/'+str(port)+'.log','a'), stderr=subprocess.STDOUT)

# 构建appium进程
appium_process = []
# 加载appium进程
for i in range(2):
    host = '127.0.0.1'
    port = 4723 +2*i
    appium = Process(target=appium_start, args=(host,port))
    appium_process.append(appium)

if __name__ == '__main__':
    for appium in appium_process:
        appium.start()
    for appium in appium_process:
        appium.join()

Appium 端口检测

端口检测

端口检测需要使用到socket模块来校验端口是否被占用。
python socket模块官方文档

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。

import socket
def check_port(host, port):
    '''检查指定的端口是否被占用'''

    # 创建socket对象
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET 是以IPV4协议进行通讯
    try:
        s.connect((host,port))
        s.shutdown(2)
    except OSError as msg:
        print('prort {0} is available!'.format(port))
        print(msg)
        return True
    else:
        print('port {0} already be in use!'.format(port))
        return False

if __name__ == '__main__':
    host = '127.0.0.1'
    port = 4723
    check_port(host,port)

方法:shutdown(self, flag):

禁止在一个Socket上进行数据的接收与发送。利用shutdown()函数使socket双向数据传输变为单向数据传输。shutdown()需要一个单独的参数, 该参数表示了如何关闭socket参数
· 0表示禁止将来读;
· 1表示禁止将来写
· 2表示禁止将来读和写。

当端口可以使用时,控制台输出如下:此使说明服务端没有开启这个端口服务,所以可用。

端口释放

import os

def release_port(port):
    '''释放指定的端口'''

    # 查找对应端口号的pid
    cmd_find = 'netstat -aon | findstr {}'.format(port)
    print(cmd_find)

    # 返回对应端口的pid
    result = os.popen(cmd_find).read()
    print(result)

    if str(port) and 'LISTENING' in result:
        # 获取端口对应的pid进程
        i = result.index('LISTENING')
        start = i+len('LISTENING')+7
        end = result.index('\n')
        pid = result[start:end]

        # 关闭被占用端口的pid
        cmd_kill = 'taskkill -f -pid {0}'.format(pid)
        print(cmd_kill)
        os.popen(cmd_kill)
    else:
        print('port {0} is available!'.format(port))

if __name__ == '__main__':
    host = '127.0.0.1'
    port = 4723
    release_port(port)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值