从 appium 迁移到了 macaca,研究了一下多机并行跑 case,总结一下,和大家一起讨论一下~~~
iOS:利用 instruments -s devices 获取连接上的所有 iOS 设备
class InitDevice:
"""
获取连接的设备的信息
"""
def __init__(self):
self.GET_ANDROID = "adb devices"
self.GET_IOS = "instruments -s devices"
def get_device(self):
value = os.popen(self.GET_ANDROID)
device = []
for v in value.readlines():
android = {}
s_value = str(v).replace("\n", "").replace("\t", "")
if s_value.rfind('device') != -1 and (not s_value.startswith("List")) and s_value != "":
android['platformName'] = 'Android'
android['udid'] = s_value[:s_value.find('device')].strip()
android['package'] = 'xxxx'
android['activity'] = 'xxxxxx'
device.append(android)
value = os.popen(self.GET_IOS)
for v in value.readlines():
iOS = {}
s_value = str(v).replace("\n", "").replace("\t", "").replace(" ", "")
if v.rfind('Simulator') != -1:
continue
if v.rfind("(") == -1:
continue
iOS['platformName'] = 'iOS'
iOS['platformVersion'] = re.compile(r'\((.*)\)').findall(s_value)[0]
iOS['deviceName'] = re.compile(r'(.*)\(').findall(s_value)[0]
iOS['udid'] = re.compile(r'\[(.*?)\]').findall(s_value)[0]
iOS['bundleId'] = 'xxxx'
device.append(iOS)
return device
判断端口号是否被占用是去执行 netstat -an | grep port这条命令判断端口号是否被占用
def is_using(port):
"""
判断端口号是否被占用
:param port:
:return:
"""
cmd = "netstat -an | grep %s" % port
if os.popen(cmd).readlines():
return True
else:
return False
def get_port(count):
"""
获得3456端口后一系列free port
:param count:
:return:
"""
port = 3456
port_list = []
while True:
if len(port_list) == count:
break
if not is_using(port) and (port not in port_list):
port_list.append(port)
else:
port += 1
return port_list
class macacaServer():
def __init__(self, devices):
self.devices = devices
self.count = len(devices)
self.url = 'http://127.0.0.1:%s/wd/hub/status'
def start_server(self):
pool = Pool(processes=self.count)
port_list = get_port(self.count)
for i in range(self.count):
pool.apply_async(self.run_server, args=(self.devices[i], port_list[i]))
pool.close()
pool.join()
def run_server(self, device, port):
r = RunServer(port)
r.start()
while not self.is_running(port):
sleep(1)
server_url = {
'hostname': "ununtrium.local",
'port': port,
}
driver = WebDriver(device, server_url)
driver.init()
DRIVER.set_driver(driver)
DRIVER.set_OS(device.get("platformName"))
self.run_test()
def run_test(self):
"""运行测试
"""
all_test = AllTests()
all_test.run_case()
def is_running(self, port):
"""Determine whether server is running
:return:True or False
"""
url = self.url % port
response = None
try:
response = requests.get(url, timeout=0.01)
if str(response.status_code).startswith('2'):
# data = json.loads((response.content).decode("utf-8"))
# if data.get("staus") == 0:
return True
return False
except requests.exceptions.ConnectionError:
return False
except ReadTimeout:
return False
finally:
if response:
response.close()
class RunServer(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
self.cmd = 'macaca server -p %s --verbose' % port
def run(self):
os.system(self.cmd)
本来想放个视频看看效果的,但是发现不会搞~~~ 我还是早点睡觉吧。。。。
又有新的东西可以学习了,赞
这个厉害~有点意思,哈哈
mark,这个确实可以,干货
我想在真机上进行 iOS 的并行测试,然后我启动了两个终端窗口,分别去执行相应的测试用例,为什么会出现两个测试用例的运行日志只在一个终端窗口输出?并且当其中一个测试用例执行完毕以后,另外一个测试用例如果即使只执行到一半,马上也会跟着一起被终止?请问这是什么情况了?
#6 楼 @AllocAndInit 启动的时候有没有指定端口,测试运行的时候有没有指定相应的端口?你这样问我只能猜,能不能上脚本和相关 log?
请更新微信或者微信二维码. testerhomer 要打赏
#8 楼 @seveniruby 已更新
def run_server(self, device, port):
r = RunServer(port)
r.start()
while not self.is_running(port):
sleep(1)
server_url = {
'hostname': "ununtrium.local",
'port': port,
}
driver = WebDriver(device, server_url)
driver.init()
DRIVER.set_driver(driver)
DRIVER.set_OS(device.get("platformName"))
self.run_test()
楼主,你的 DRIVER.set_driver(driver),driver 是怎么传递的?这个地方能详细解释一下吗?
#11 楼 @tongshanshanshan 嗯,差不多啊,我也是这样用的,
class DRIVER:
driver = None
传值的时候,DRIVER.driver = driver(后面的 driver 为获取到的),那么,driver 到这里后,api 调用的时候呢?
#13 楼 @tongshanshanshan 这个肯定是没问题的,其实我想知道的是,比如我进行 api 的一些二次封装,我肯定要传 driver 进来的,我现在遇到的问题是,比如我的二次封装类为 Element,初始化的时候 self.driver = DRIVER.driver,那么会取到 set_driver 传进来的 driver 么?
#15 楼 @tongshanshanshan 我现在的做法是,直接在 Element 这里取 driver,其他地方不再取了,不过还没驱动起来, ,既然确定了设计思路没问题,那就再试试,多谢楼主,我再调试一下,实在不行,再跟你请教
@tongshanshanshan 你好,咨询下,有点没看懂你这么做的含义.意思是 你这套 py 脚本 是跑在一个 "测试执行服务环境" 的吗?
那么 这个"测试执行服务环境" 是一个什么平台下的环境 是支持 android APP 测试的 环境 还是支持 ios APP 测试的环境?
这个测试执行服务环境 不可能既是 android 又是 ios 的吧?
还是 你这个脚本 是去两套测试执行环境下去分别驱动 andriod 和 ios 的 否则 怎么叫 Android 和 iOS 并行测试.
这个并行 是在一套测试环境下的 还是 分别两套安卓和苹果环境下的?
楼主可以给个 windows,安卓版本用的软件么?Node.js 和需要 Node.js 安装的东西
#18 楼 @tongshanshanshan 就是跑用例的自动化测试服务环境,我们目前就是一台电脑 ubuntu16.04,部署了 macaca-cli 和 macaca-android 还有就是 android-sdk 执行环境,只能跑安卓 app 的用例。要是跑 ios app 的话那不是得 mac 系统环境吗?你这套脚本可以同时一个环境下去检测连接到这个环境的 ios 和 android?同时在这个环境下去并行安卓和苹果 app 用例?
是的,这可以的。但是我的电脑是 mac。
#21 楼 @tongshanshanshan 看来自动化测试服务器 还是要一步到位弄个 mac 机 这样既可以连 ios 机又可以连 android 机....
pool.apply_async(self.run_server, args=(self.devices[i], port_list[i])
和
class RunServer(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
self.cmd = 'macaca server -p %s --verbose' % port
def run(self):
os.system(self.cmd)
这两段启动 macaca server port 的代码,我运行没有成功,apply_async 运行时根本没有调用 run_server 方法。还有 macaca server -p %s --verbose 是否需要守护进程去调用,服务会一直保持启动,apply_async 不会回到主进程?
result = []
result.append(pool.apply_async(self.run_server, args=(self.devices[i], port_list[i]))
for res in result:
print(res.get())
def run_server(self, device, port):
r = RunServer(port)
r.start()
while not self.is_running(port):
sleep(1)
server_url = {
'hostname': "ununtrium.local",
'port': port,
}
driver = WebDriver(device, server_url)
driver.init()
DRIVER.set_driver(driver)
DRIVER.set_OS(device.get("platformName"))
self.run_test()
driver = WebDriver(device, server_url)
driver.init()
threadpool = []
for i in range(self.count):
t = RunThread(self.devices[i],pool_list[i])
threadpool.append(t)
for j in threadpool:
j.start()
for k in threadpool:
k.join()
现在手机和模拟器的 WDA 都能自动 build 上去,但是运行用例的时候,只能跑一台机器,有一个会 [ ERROR ] Message: Session does not exist ,请问是哪里用错了么?
driver = WebDriver(device, server_url)
driver.init()
这个方法不是我实现的,是 macaca 自己封装好,用来初始化 driver 的。
pool.apply_async(self.run, (self.devices[i], pool_list[i])) 并行执行不了,一运行就结束了
这个是因为在在执行 self.run 这个方法的过程中报错了,所以提前结束。但是并没有把报错信息给打印出来。你可以添加以下代码,就可以看见报错信息了。
result = []
result.append(pool.apply_async(self.run_server, args=(self.devices[i], port_list[i]))
for res in result:
print(res.get())
至于最后一个 [ ERROR ] Message: Session does not exist:
你确定所有服务都起来之后才运行用例的么?
#26 楼 @tongshanshanshan 现在改用 pool.apply_async,我把进程 id 也给打印出来,发现两次的进程 id 居然是一样的,不科学啊。
result = []
for i in range(self.count):
print 'device = %s,port: %s' % (self.devices[i],str(pool_list[i]))
print 'Run task %s (%s)...' % (i, os.getpid())
res_pool = pool.apply_async(self.run, (self.devices[i], pool_list[i]))
result.append(res_pool)
pool.close()
pool.join()
print 'All subprocesses done.'
for res in result:
print res.get
日志
进程数: 2
端口列表: [4723, 4724]
Run task 0 (59622)...
Run task 1 (59622)...
All subprocesses done.
<bound method ApplyResult.get of <multiprocessing.pool.ApplyResult object at 0x1059bc310>>
<bound method ApplyResult.get of <multiprocessing.pool.ApplyResult object at 0x1059bc390>>
appium 相关进程列表 = ['59652\n']
CleanProcess:Darwin:kill appium
#28 楼 @tongshanshanshan 确实哦,没注意看,现在把打印加入到 run 里面了,但是没有日志输出
进程数: 2
端口列表: [4723, 4724]
All subprocesses done.
<bound method ApplyResult.get of <multiprocessing.pool.ApplyResult object at 0x10bc72310>>
<bound method ApplyResult.get of <multiprocessing.pool.ApplyResult object at 0x10bc72390>>
appium 相关进程列表 = ['60663\n']
CleanProcess:Darwin:kill appium
#30 楼 @tongshanshanshan 你看上面的日志,有打印啊,print res.get() 这样用会报错 “cPickle.PicklingError: Can't pickle : attribute lookup builtin.instancemethod failed”
#30 楼 @tongshanshanshan 还是得请教你,那个 pid 的问题已经解决了。现在问题好奇怪,我一台模拟器,一台手机,结果设置参数串了,目前单独跑都没问题,一并行跑,就只能跑一台,但是两台的 wda 都能 build 上,其中真机系统版本 10.0.2,模拟器 10.2,但是真机日志中发现出现了 10.2 的系统版本,有点懵了,你能看出问题么?
代码:
def Run_one(device,port):
print 'Run task %s (%s) at %s' % (str(port), os.getpid(), time.ctime())
S.set_device(device)
from src.lib.Log import LogSignleton
logsignleton = LogSignleton(device)
logger = logsignleton.logger
L.set_logger(logger)
print '*' * 80
print time.ctime(),' [', __name__, '::', Run_one.__name__, '] :', ' logger = ', logger
# 启动appium 服务
appium_server.start_server(device, port)
# 实例化Dirver
Dr = Driver(device, port)
Dr.init() # 初始化driver
driver = Dr.getDriver()
D.set_driver(driver)
print '*' * 80
print time.ctime(),' [', __name__, '::', Run_one.__name__, '] :', ' driver = ', driver
# 生成runner
runner = unittest.TextTestRunner()
# 循环遍历测试用例列表
for case_list in case_sheet1[1:]:
test_suite = __get_test_suite(case_list)
runner.run(test_suite)
# 生成测试报告
RunExcel.get_html_report()
# run_mode() # 运行模式
if __name__ == '__main__':
appium_server = AppiumServer()
devices = appium_server.get_device()
count = len(devices)
ports = appium_server.get_port(count)
print 'Run task pid: (%s) at: %s' % ( os.getpid(), time.ctime())
print '*'*80
p = Pool(count)
for i in range(count):
p.apply_async(Run_one,(devices[i],ports[i],))
p.close()
p.join()
print 'All finished'
真机
appium -a 127.0.0.1 -p 4724 -U bcf1530f7fae062a4433b658b75f4bde43aaf15f
[debug] [XCUITest] Waiting up to 60000ms for WebDriverAgent to start
[debug] [XCUITest] Log file for xcodebuild test: /Users/zengyuanchen/Library/Developer/Xcode/DerivedData/WebDriverAgent-fuwmnzdhnozghbgmpkthbcubvqlr/Logs/Test/0F3BAEF0-6655-49DC-9B93-A987D6305E75/Session-WebDriverAgentRunner-2017-01-12_114216-Yga1Hy.log
[debug] [XCUITest] WebDriverAgent successfully started after 14389ms
[debug] [iProxy] recv failed: Resource temporarily unavailable
[debug] [iProxy] recv failed: Operation not permitted
[debug] [XCUITest] Sending createSession command to WDA
[debug] [JSONWP Proxy] Proxying [POST /session] to [POST http://localhost:8100/session] with body: {"desiredCapabilities":{"bundleId":"rym.pingan.rympush","arguments":[],"environment":{},"shouldWaitForQuiescence":true}}
[debug] [JSONWP Proxy] Got response with status 200: {"value":{"sessionId":"9DDA03DA-857B-4768-957D-C81CD9B1C2A4","capabilities":{"device":"iphone","browserName":"任意门","sdkVersion":"10.0.2","CFBundleIdentifier":"rym.pingan.rympush"}},"sessionId":"9DDA03DA-857B-4768-957D-C81CD9B1C2A4","status":0}
[debug] [XCUITest] Setting initial orientation to 'PORTRAIT'
[debug] [JSONWP Proxy] Proxying [POST /orientation] to [POST http://localhost:8100/session/9DDA03DA-857B-4768-957D-C81CD9B1C2A4/orientation] with body: {"orientation":"PORTRAIT"}
[debug] [iProxy] recv failed: Resource temporarily unavailable
[debug] [iProxy] recv failed: Operation not permitted
[debug] [JSONWP Proxy] Got response with status 200: {"value":{},"sessionId":"9DDA03DA-857B-4768-957D-C81CD9B1C2A4","status":0}
[Appium] New XCUITestDriver session created successfully, session 23b7a53e-9784-43c8-8b25-f9b6db07c151 added to master session list
[debug] [MJSONWP] Responding to client with driver.createSession() result: {"webStorageEnabled":false,"locationContextEnabled":false,"browserName":"","platform":"MAC","javascriptEnabled":true,"databaseEnabled":false,"takesScreenshot":true,"networkConnectionEnabled":false,"deviceName":"Rym'iPhone","udid":"bcf1530f7fae062a4433b658b75f4bde43aaf15f","autoAcceptAlerts":true,"automationName":"XCUITest","noReset":true,"WaitForAppScript":true,"platformVersion":"10.2","platformName":"iOS","bundleId":"rym.pingan.rympush"}
[HTTP] <-- POST /wd/hub/session 200 21123 ms - 514
下面是模拟器
模拟器
appium -a 127.0.0.1 -p 4723 -U 32E6D124-29B6-48A2-9B38-0A9D54121E10
[debug] [XCUITest] WebDriverAgent successfully started after 829ms
[debug] [XCUITest] Sending createSession command to WDA
[debug] [JSONWP Proxy] Proxying [POST /session] to [POST http://localhost:8100/session] with body: {"desiredCapabilities":{"bundleId":"rym.pingan.rympush","arguments":[],"environment":{},"shouldWaitForQuiescence":true}}
[debug] [JSONWP Proxy] Got response with status 200: {"value":{"sessionId":"A85E029D-38D3-407F-96E0-44020D1279C7","capabilities":{"device":"iphone","browserName":"任意门","sdkVersion":"10.0.2","CFBundleIdentifier":"rym.pingan.rympush"}},"sessionId":"A85E029D-38D3-407F-96E0-44020D1279C7","status":0}
[debug] [XCUITest] Setting initial orientation to 'PORTRAIT'
[debug] [JSONWP Proxy] Proxying [POST /orientation] to [POST http://localhost:8100/session/A85E029D-38D3-407F-96E0-44020D1279C7/orientation] with body: {"orientation":"PORTRAIT"}
[debug] [JSONWP Proxy] Got response with status 200: {"value":{},"sessionId":"A85E029D-38D3-407F-96E0-44020D1279C7","status":0}
[Appium] New XCUITestDriver session created successfully, session 128bc2f7-3c59-4495-a9b5-e77cf62e5565 added to master session list
[debug] [MJSONWP] Responding to client with driver.createSession() result: {"webStorageEnabled":false,"locationContextEnabled":false,"browserName":"","platform":"MAC","javascriptEnabled":true,"databaseEnabled":false,"takesScreenshot":true,"networkConnectionEnabled":false,"deviceName":"iPhone6s","udid":"32E6D124-29B6-48A2-9B38-0A9D54121E10","autoAcceptAlerts":true,"automationName":"XCUITest","noReset":true,"WaitForAppScript":true,"platformVersion":"10.2","platformName":"iOS","bundleId":"rym.pingan.rympush"}
[HTTP] <-- POST /wd/hub/session 200 22330 ms - 508
#33 楼 @tongshanshanshan 这个方法基本是按照你的样例写的
def get_device(self):
'''
获取真实设备列表
:param deviceName:
:param deviceType:
:return:
'''
# 存储设备信息
device = []
# value_ios = os.popen(self.Get_iOS)
isMonitor = eval(read_config('appium', 'isMonitor'))
# 获取模拟器设备列表
if isMonitor:
iOS_Monitor = {}
deviceName = read_config('appium', 'deviceName')
platformVersion = read_config('appium', 'platformVersion')
iOS_Monitor['deviceName'] = deviceName
# deviceName = str(deviceName).replace(' ','')
for dev in os.popen(self.Get_iOS).readlines():
dev_value = str(dev).replace("\n", "").replace("\t", "").replace(" ", "")
# print dev_value
if dev_value.rfind(deviceName) == -1:
continue
if dev_value.rfind(platformVersion) == -1:
continue
# print dev_value
re_deviceName = re.compile(r'(.*)\(').findall(dev_value)[0]
re_deviceName2 = re.compile(r'(.*)\(').findall(re_deviceName)[0]
# print 're_deviceName2: ' , re_deviceName2
# print 'deviceName: ',deviceName
if re_deviceName2 != deviceName:
continue
# if re_deviceName != deviceName:
# continue
iOS_Monitor['udid'] = re.compile(r'\[(.*?)\]').findall(dev_value)[0]
iOS_Monitor['platformVersion'] = platformVersion
iOS_Monitor['platformName'] = 'iOS'
device.append(iOS_Monitor)
else:
pass
# 是否运行真机
isRealDevice = eval(read_config('appium', 'isRealDevice'))
if isRealDevice:
# 获取iOS真实设备列表
for dev in os.popen(self.Get_iOS).readlines():
iOS = {}
Android = {}
dev_value = str(dev).replace("\n", "").replace("\t", "").replace(" ", "")
if dev.rfind('Simulator') != -1:
continue
if dev.rfind('(') == -1:
continue
# print dev_value
# iOS['platformName'] = read_config('appium', 'platformName')
# iOS['bundleId'] = read_config('appium','bundleId')
iOS['deviceName'] = re.compile(r'(.*)\(').findall(dev_value)[0]
iOS['platformVersion'] = re.compile(r'\((.*)\)').findall(dev_value)[0]
iOS['udid'] = re.compile(r'\[(.*?)\]').findall(dev_value)[0]
iOS['platformName'] = 'iOS'
device.append(iOS)
# print iOS
# 命令获取Android设备列表
for dev in os.popen(self.Get_Android).readlines():
dev_value = str(dev).replace("\n", "").replace("\t", "")
if dev_value.rfind('device') != -1 and (not dev_value.startswith("List")) and dev_value != "":
Android['udid'] = dev_value[:dev_value.find('device')].strip()
Android['platformName'] = 'Android'
device.append(Android)
else:
pass
print time.ctime(), ' [', __name__, '::', AppiumServer.get_device.__name__, '] :', ' device = ', device
return device
#33 楼 @tongshanshanshan 这个方法应该是没什么问题,获取的信息也是对的,单独调试这个方法可以获取到正确的设备信息。从我调试的结果来看,driver 初始化的时候,这里的日期打印时间,两个设备不是同一个时间,其他包括启动 appium 的服务,获取设备信息都是同一个时间(差几秒),所以,是不是 driver 这里有问题?
@tongshanshanshan 而且更奇葩的是,我出现过不少次,感觉线程堵塞了,就是设备用例跑不起来,杀掉 node 都不行,需要重启电脑才可以,还有把我 5s 手机给跑的发烫,然后卡的要死,也要重启才会好。从开始弄多线程,都快疯了都。。。
#36 楼 @Tank007 这边啊
[debug] [JSONWP Proxy] Proxying [POST /session] to [POST http://localhost:8100/session] with b 为啥是都是 8100 端口,你这里不是设置的端口号是 4724 么?
#37 楼 @tongshanshanshan 我也不知道啊,这个是 wda 的默认端口,会不会和 appium 的端口没有关系?单独跑的时候也没见跑不了啊
#39 楼 @tongshanshanshan 你那边运行的时候,有这种端口问题么?用 macaca 的时候
没有,我只要设置 macaca server 运行的端口就行了。
#41 楼 @tongshanshanshan 一个道理啊,我也是只要设置 appium 运行的端口就可以了,不应该啊,macaca 也调用 wda 的,也有默认端口的呀
#42 楼 @Tank007 我刚刚运行了一下,发现用的是 2 个不同的端口。
>> xctest-client.js:56:14 [master] pid:10556 project path: /usr/local/lib/node_modules/macaca-ios/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> xctest-client.js:56:14 [master] pid:10555 project path: /usr/local/lib/node_modules/macaca-ios/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> macaca-ios.js:147:10 [master] pid:10556 {
"bundleId": "com.btcc.mobiEntStaging",
"platformVersion": "9.3.5",
"platformName": "iOS"
}
>> macaca-ios.js:147:10 [master] pid:10555 {
"bundleId": "com.btcc.mobiEntStaging",
"platformVersion": "10.0.1",
"platformName": "iOS"
}
>> macaca-ios.js:151:12 [master] pid:10556 Trying to start wda server...
>> macaca-ios.js:151:12 [master] pid:10555 Trying to start wda server...
(node:10556) DeprecationWarning: Calling an asynchronous function without callback is deprecated.
(node:10555) DeprecationWarning: Calling an asynchronous function without callback is deprecated.
(node:10555) DeprecationWarning: Calling an asynchronous function without callback is deprecated.
(node:10556) DeprecationWarning: Calling an asynchronous function without callback is deprecated.
BundleId com.apple.test.WebDriverAgentRunner-Runner does not exist.
>> xctest-client start with port: 8900
>> xctest-client.js:233:14 [master] pid:10556 xcode version: 8.2
>> WebDriverAgent version: 1.0.38
>> xctest-client start with port: 8901
>> xctest-client.js:233:14 [master] pid:10555 xcode version: 8.2
>> WebDriverAgent version: 1.0.38
#43 楼 @tongshanshanshan 嗯,那么问题来了,我怀疑是我这边用的是同一个端口,我再仔细看看
@tongshanshanshan 这两个设备用的 wda 的同一个端口进行通信,都是 8100,是这个问题么?
#44 楼 @tongshanshanshan 是并行的 log,我分别手动开了两个 appium 的服务,然后分别截取的日志
@seveniruby 请教一个问题,多台设备并发使用 appium 的服务,所有设备都使用一个端口(8100),还是使用不同的端口,macaca 是用不同的端口耶
#49 楼 @tongshanshanshan 跟你启动 macaca 差不多,都是一条命令,appium -a ip -p port,这个 port 就是启动的 appium 的端口,目前还没看到过指定 wda 的端口
#49 楼 @tongshanshanshan wda 启动成功后的日志
2017-01-12 16:49:00.609 XCTRunner[10928:159660] Running tests...
2017-01-12 16:49:02.465 XCTRunner[10928:159660] Continuing to run tests in the background with task ID 1
Test Suite 'Selected tests' started at 2017-01-12 16:49:03.066
Test Suite 'WebDriverAgentRunner.xctest' started at 2017-01-12 16:49:03.067
Test Suite 'UITestingUITests' started at 2017-01-12 16:49:03.068
Test Case '-[UITestingUITests testRunner]' started.
t = 0.00s Start Test at 2017-01-12 16:49:03.069
t = 0.00s Set Up
2017-01-12 16:49:03.077 XCTRunner[10928:159660] Built at Jan 6 2017 09:14:36
2017-01-12 16:49:03.136 XCTRunner[10928:159660] ServerURLHere->http://10.180.185.159:8100<-ServerURLHere
#52 楼 @tongshanshanshan 目前从日志来看,是这样的
这是一台 iOS 和一台 Android 同时测试,还是支持多台 iOS 同时测试啊?
#55 楼 @tongshanshanshan
请问是不是也支持一台 mac 同时连接多台 iOS 啊?据说 appium 不支持一台 mac 连接多台 iOS 设备测试
感谢
@tongshanshanshan 请问楼主 ,你有试过在 多台 iOS 真机设备上并发执行测试用例过吗?是否了解 Macaca 有一个最大的并发数?我自己现在在 两台 iOS 真机设备上并行测试没什么问题,但是一旦添加一台设备以后,也就是 3 台设备同时测试的时候,总会出现一些莫名其妙的问题,而且也总是 有一台设备无法正常启动测试用例,而且还会 一直报 xctest client proxy error with: Error: socket hang up 这样的错误 ,请问楼主有碰到过这样的问题吗?
#28 楼 @tongshanshanshan 楼主的文章很好,就是对于小白来说很多看不懂,可以教教我怎么快速上手进行真机测试吗?非常想学,可是没头绪,谢谢楼主。
pool = Pool(processes=self.count)
这里的 Pool 是什么?
操作事件我都封装到 element 里面了,如果里面想用 driver 是不是 driver = DVIVER.driver 就可以了
except ReadTimeout 这个是需要导入,还是自己创建一个 py 文件
#63 楼 @tongshanshanshan 导入我的 import ReadTimeout ,会提示 ReadTimeout 不存在,是需要导入到 pycharm 什么文件呢
except requests.exceptions.ReadTimeout:
return False
楼主,按照你的这种代码,我运行了一个 demo,调用 start_server 会先执行 case,再搜索手机,端口信息
打完断点,都没有经过 run_server 方法,就结束了,也没有报错
楼主,我的执行以后发现会先执行给 element.py 二次封装事件中的 driver= DRIVER.driver 先赋值 None,后续不再赋值了,导致调用 driver.element('','') 时报错,能把你的框架思路简单说下嘛,如何在其他文件里面正常调用 driver
关于 macaca 的并发测试https://testerhome.com/topics/7499
我这边也出现了和上边你们讨论的和 Appium 一模一样的问题。不知道为什么? @Tank007
#72 楼 @sixleaves 你的问题具体是什么,还没搞明白,是同一个端口么?
#71 楼 @tongshanshanshan 楼主,两部手机只有一个能启动起来
#71 楼 @tongshanshanshan 单个手机运行时,同样的代码不同的手机,但是其他测试机在我的项目里运行启动不起来,我的手机怎么启动都可以,什么原因呢. 不加入你的并发执行的代码,两个手机单独还能正常执行
@tongshanshanshan github 分享一下啊
#80 楼 @tongshanshanshan 不加入并行执行的代码,只用我写的简单的 Demo 两个手机分别执行没有问题。但是用并行执行的代码,只能一个手机能够启动应用程序。是这样的
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from macaca import WebDriver
import time
from parameters.conf_server import *
import threading
import requests
from multiprocessing.pool import Pool
from middleware.all_case import *
from parameters.run import *
from parameters.configure import *
from parameters.conf_driver import *
from parameters.conf_client import *
# class macacaServer():
# def __init__(self, devices):
#
# self.devices = devices
# self.count = len(devices)
# self.url = 'http://127.0.0.1:%s/wd/hub/status'
def start_server(devices):
# 进程池
count = len(devices)
pool = Pool(processes=count)
port_list = get_port(count)
for i in range(count):
pool.apply_async(run_server, args=(devices[i], port_list[i]))
time.sleep(3)
#self.run_server(self.devices[i],port_list[i])
pool.close()
pool.join()
def run_server(device, port):
r = RunServer(port)
r.start()
while not is_running(port):
time.sleep(1)
server_url = {
'hostname': server_ip,
'port': port,
}
driver = WebDriver(device, server_url)
driver.init()
DRIVER.set_driver(driver)
DRIVER.set_OS(device.get("platformName"))
run_test(driver)
def run_test(driver):
"""
运行测试
"""
test_run(driver,login_pages)
def is_running(port):
"""Determine whether server is running
:return:True or False
"""
url = 'http://127.0.0.1:%s/wd/hub/status'
url1 = url % port
response = None
try:
response = requests.get(url1, timeout=0.01)
if str(response.status_code).startswith('2'):
return True
return False
except requests.exceptions.ConnectionError:
return False
except requests.exceptions.ReadTimeout:
return False
finally:
if response:
response.close()
class RunServer(threading.Thread):
def __init__(self, port):
threading.Thread.__init__(self)
self.cmd = 'macaca server -p %s --verbose' % port
def run(self):
os.system(self.cmd)
if __name__ == "__main__":
b = InitDevice()
start_server(b.get_device())
>> xctest-client.js:171:14 [master] pid:2654 please check project: /usr/local/lib/node_modules/macaca-ios/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> proxy.js:56:14 [master] pid:2654 Proxy: /session:POST to http://127.0.0.1:8900/session:POST with body: {"desiredCapabilities":{"bundleId":"","platformVersion":"9.1","platformName":"iOS"}}
>> proxy.js:62:22 [master] pid:2654 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2654 xctest client proxy error with: Error: socket hang up
>> xctest-client.js:170:14 [master] pid:2654 writeDictToFile:1278 ==== Successfully wrote Manifest cache to /var/folders/0q/d31vt2395c3gd028gzysbx3r0000gp/C/com.apple.DeveloperTools/All/Xcode/EmbeddedAppDeltas/3c13836573226534d387cb31a1801fd8/aa7cee10b392d3661bd40d4e46778e89e35a6511/ManifestCache.plist
>> xctest-client.js:171:14 [master] pid:2654 please check project: /usr/local/lib/node_modules/macaca-ios/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> proxy.js:62:22 [master] pid:2654 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2654 xctest client proxy error with: Error: socket hang up
>> proxy.js:84:20 [master] pid:2654 Got response with status 200: {"value":{"sessionId":"87BB2534-5D9B-433F-B6BE-3CC2B74F5E4F","capabilities":{"device":"iphone","browserName":"Mobi","sdkVersion":"9.1","CFBundleIdentifier":"com.btcc.mobiEntStaging"}},"sessionId":n...
>> responseHandler.js:47:14 [master] pid:2654 Send HTTP Respone to Client: {"sessionId":"38401d3f-62a8-4c4e-af07-8d930d8bf65d","status":0,"value":"{\"bundleId\":\"com.btcc.mobiEntStaging\",\"platformVersion\":\"9.1\",\"deviceName\":\"BTCCiPodtouch\",\"platformName\":\"iOS\",\"udid\":\"aa7cee10b392d3661bd40d4e46778e89e35a6511\"}"}
>> responseHandler.js:11:12 [master] pid:2654 Recieve HTTP Request from Client: method: POST url: /wd/hub/session/38401d3f-62a8-4c4e-af07-8d930d8bf65d/element, jsonBody: {"using":"name","value":"me"}
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> proxy.js:62:22 [master] pid:2740 xctest client proxy error with: Error: socket hang up
>> xctest-client.js:257:14 [master] pid:2740 Fail to start xctest: Error: socket hang up
>> xctest-client.js:265:14 [master] pid:2740 killing deviceLogProc pid: 3163
>> xctest-client.js:270:14 [master] pid:2740 killing runnerProc pid: 3166
>> xctest-client.js:276:14 [master] pid:2740 killing iproxyProc pid: 3165
>> responseHandler.js:54:12 [master] pid:2740 Send Error Respone to Client: Error: socket hang up
我的不会重连,然后报错,有解决方案么?