Appium 并发测试基于unitest
前言:
在回歸測試階段,UI測試,兼容測試是測試的必要步驟。UI自動化的本身是比較冗余的測試,但是換個角度思考,UI自動化同時連接多臺設備,那么在回歸測試時,在同一個腳本下產生的測試結果是非常有價值的。
不同設備在并發下的測試結果可以為我們提供:
1. 兼容性測試(不同的手機品牌,Android版本, 分辨率等)
2. 性能測試(通過安裝Emmagee,監控不同手機在同腳本下,性能的變化)
3. 界面對比(通過圖像識別opencv,截圖對比等 查看在相同頁面的變化)
?
思路:
1. 啟動多路appium服務
2. 啟動并連接多路手機端
3. 運行并生成測試報告
?
問題:
1. python的unittest框架和java不同,不支持參數傳入,可以通過重寫unittest.TestCase的init添加參數
2. appium 通過命令行啟動,需要安裝非desktop的版本,且最好安裝1.9版本appium,1.0我啟動不了
?
框架代碼截取:
1. 重寫unittest的初始化函數
class ParametrizedCase(unittest.TestCase):def __init__(self, methodName='runTest', param=None):super(ParametrizedCase, self).__init__(methodName)global devicesdevices = param@classmethoddef setUpClass(cls):cls.driver = connect_device(devices)@classmethoddef tearDownClass(cls):cls.driver.close_app()cls.driver.quit()
?
2. 封裝啟動appium的服務方法:
基于 appium 的啟動命令
appium -p -bp -U
封裝多線程啟動
class AppiumServer:def __init__(self, kwargs=None):self.kwargs = kwargsdef start_server(self):"""start the appium server"""for i in range(0, len(self.kwargs)):cmd = "appium --session-override -p %s -bp %s -U %s" % (self.kwargs[i]["port"], self.kwargs[i]["bport"], self.kwargs[i]["devices"])print(cmd)if platform.system() == "Windows": # windows下啟動servert1 = RunServer(cmd)p = Process(target=t1.start())p.start()while True:print("--------start_win_server-------------")if self.win_is_runnnig("http://127.0.0.1:" + self.kwargs[i]["port"] + "/wd/hub" + "/status"):print("-------win_server_ 成功--------------")breakelse:appium = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1,close_fds=True)while True:appium_line = appium.stdout.readline().strip().decode()time.sleep(1)print("---------start_server----------")if 'listener started' in appium_line or 'Error: listen' in appium_line:print("----server_ 成功---")breakdef win_is_runnnig(self, url):"""Determine whether server is running:return:True or False"""response = Nonetime.sleep(1)try:response = urllib.request.urlopen(url, timeout=5)if str(response.getcode()).startswith("2"):return Trueelse:return Falseexcept URLError:return Falseexcept socket.timeout:return Falsefinally:if response:response.close()def stop_server(self, devices):sysstr = platform.system()if sysstr == 'Windows':os.popen("taskkill /f /im node.exe")else:for device in devices:# maccmd = "lsof -i :{0}".format(device["port"])plist = os.popen(cmd).readlines()plisttmp = plist[1].split(" ")plists = plisttmp[1].split(" ")# print plists[0]os.popen("kill -9 {0}".format(plists[0]))class RunServer(threading.Thread):def __init__(self, cmd):threading.Thread.__init__(self)self.cmd = cmddef run(self):os.system(self.cmd)
?
3. 封裝連接Android設備的方法:
def connect_device(devices):desired_caps = {}desired_caps['platformVersion'] = devices["platformVersion"]desired_caps['platformName'] = devices["platformName"]desired_caps["automationName"] = devices['automationName']desired_caps['deviceName'] = devices["deviceName"]desired_caps["appPackage"] = devices["appPackage"]desired_caps["appActivity"] = devices["appActivity"]desired_caps["noReset"] = Truedesired_caps['noSign'] = Truedesired_caps["unicodeKeyboard"] = Truedesired_caps["resetKeyboard"] = Truedesired_caps["systemPort"] = devices["systemPort"]# desired_caps['app'] = devices["app"]remote = "http://127.0.0.1:" + str(devices["port"]) + "/wd/hub"# remote = "http://127.0.0.1:" + "4723" + "/wd/hub"driver = webdriver.Remote(remote, desired_caps)return driver
?
4. 多線程啟動服務和多線程連接多終端,生成日志報告
def runnerPool(getDevices):devices_Pool = []for i in range(0, len(getDevices)):_initApp = {}_initApp["deviceName"] = getDevices[i]["devices"]_initApp["platformVersion"] = getPhoneInfo(devices=_initApp["deviceName"])["release"]_initApp["platformName"] = "Android"_initApp["port"] = getDevices[i]["port"]_initApp["automationName"] = "UiAutomator2"_initApp["systemPort"] = getDevices[i]["systemPort"]_initApp["appPackage"] = 'cn.vsx.vc'_initApp["appActivity"] = '.activity.RegistActivity'devices_Pool.append(_initApp)print(f'devices pool are {devices_Pool}')with ProcessPoolExecutor(len(devices_Pool)) as pool:pool.map(runnerCaseApp, devices_Pool)def runnerCaseApp(devices):suite = unittest.TestSuite()suite.addTest(ParametrizedCase.parametrize(group_call, param=devices)) # 加入測試類now = time.strftime('%Y-%m-%d %H_%M_%S')result = BeautifulReport(suite)result.report(filename=now + f"_{devices['deviceName'].split(':', 1)[0]}.html", log_path='E:\\TestReports\\',description=f"{devices['deviceName'].split(':', 1)[0]}")if __name__ == '__main__':devices = attached_devices()if len(devices) > 0:l_devices = []for dev in devices:app = {}app["devices"] = devapp["port"] = str(random.randint(4700, 4900))app["bport"] = str(random.randint(4700, 4900))app["systemPort"] = random.randint(4700, 4900)l_devices.append(app)print(f'list of server:{l_devices}')appium_server = AppiumServer(l_devices)appium_server.start_server()runnerPool(l_devices)appium_server.stop_server(l_devices)else:print("沒有可用的安卓設備")
以上為大體的運行思路,只截取部分代碼,其他的缺失代碼可自行思考
?
思路擴展:
1. unittest框架希望升級成pytest框架更靈活,支持的插件也更多。?
2. allure報告支持pytest,更詳細美觀且可支持Jenkins持續集成
3. 可替換appium為阿里的macaca
(全平臺支持,不限制移動端
更專業的 Node 模塊開發和封裝
驅動更加快速、穩定
本地到持續集成的方案提供
技術棧更新更快
協議更自由 MIT
全面的技術支持
在國內社區更有優勢) 當然 appium也不錯,實在下載不了就考慮macaca
4. atx uiautomator2 的模式也可以參考,優勢在于可通過WiFi進行多手機并發
轉載于:https://www.cnblogs.com/grandlulu/p/10282201.html
總結
以上是生活随笔為你收集整理的Appium 并发测试基于unitest的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小车轮胎侧面有裂纹需要更换吗?
- 下一篇: 面膜多少钱一张啊?