<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
第一步:從裝置池當中,獲取當前連線的裝置。若裝置池為空,則無裝置連線。
第二步:若裝置池不為空,啟動一個執行緒,用來啟動appium server.與裝置個數對應。
起始server埠為4723,每多一個裝置,埠號預設+4
第三步:若裝置池不為空,則啟用多個執行緒,來執行app自動化測試。
定義一個 ManageDevices 類。
1. 重啟adb服務。
2. 通過adb devices命令獲取當前平臺中,已連線的裝置個數,和裝置uuid.
3. 通過adb -P 5037 -s 裝置uuid shell getprop ro.build.version.release獲取每一個裝置的版本號。
4. 將所有已連線裝置的裝置名稱、裝置版本號儲存在一個列表當中。
5. 通過呼叫get_devices_info函數,即可獲得4中的列表。
實現的部分程式碼為:
""" @Title : app多裝置並行-appium+pytest @Author : 檸檬班-小簡 @Email : lemonban_simple@qq.com """ class ManageDevices: """ 1、重啟adb服務。 2、通過adb devices命令獲取當前平臺中,已連線的裝置個數,和裝置uuid. 3、通過adb -P 5037 -s 裝置uuid shell getprop ro.build.version.release獲取每一個裝置的版本號。 4、將所有已連線裝置的裝置名稱、裝置版本號儲存在一個列表當中。 5、通過呼叫get_devices_info函數,即可獲得4中的列表。 """ def __init__(self): self.__devices_info = [] # 重啟adb服務 self.__run_command_and_get_stout("adb kill-server") self.__run_command_and_get_stout("adb start-server") def get_devices_info(self): """ 獲取已連線裝置的uuid,和版本號。 :return: 所有已連線裝置的uuid,和版本號。 """ self.__get_devices_uuid() print(self.__devices_info) self.__get_device_platform_vesion() return self.__devices_info
裝置啟動引數管理池。
每一個裝置:對應一個啟動引數,以及appium服務的埠號。
1. desired_caps_config/desired_caps.yaml檔案中儲存了啟動引數模板。
2. 從1中的模板讀取出啟動引數。
3. 從裝置列表當中,獲取每個裝置的裝置uuid、版本號,與2中的啟動引數合併。
4. 每一個裝置,指定一個appium伺服器埠號。從4723開始,每多一個裝置,預設遞增4
5. 每一個裝置,指定一個本地與裝置tcp通訊的埠號。從8200開始,每多一個裝置,預設遞增4.
在啟動引數當中,通過systemPort指定。
因為appium服務會指定一個本地埠號,將資料轉發到安卓裝置上。
預設都是使用8200埠,當有多個appium服務時就會出現埠衝突。會導致執行過程中出現socket hang up的報錯。
實現的部分程式碼:
def devices_pool(port=4723,system_port=8200): """ 裝置啟動引數管理池。含啟動引數和對應的埠號 :param port: appium服務的埠號。每一個裝置對應一個。 :param system_port: appium服務指定的本地埠,用來轉發資料給安卓裝置。每一個裝置對應一個。 :return: 所有已連線裝置的啟動引數和appium埠號。 """ desired_template = __get_yaml_data() devs_pool = [] # 獲取當前連線的所有裝置資訊 m = ManageDevices() all_devices_info = m.get_devices_info() # 補充每一個裝置的啟動資訊,以及設定對應的appium server埠號 if all_devices_info: for dev_info in all_devices_info: dev_info.update(desired_template) dev_info["systemPort"] = system_port new_dict = { "caps": dev_info, "port": port } devs_pool.append(new_dict) port += 4 system_port += 4 return devs_pool
特別注意事項:2 個及 2 個以裝置並行時,會遇到裝置 socket hang up 的報錯。
原因是什麼呢:
在 appium server 的紀錄檔當中,有這樣一行 adb 命令:adb -P 5037 -s 08e7c5997d2a forward tcp:8200 tcp:6790
什麼意思呢?
將本地 8200 埠的資料,轉發到安卓裝置的 6790 埠
所以,本地啟動多個 appium server,都是用的 8200 埠,就會出現衝突。
解決方案:
應該設定為,每一個 appium server 用不同的本地埠號,去轉發資料給不同的裝置。
啟動引數當中:新增systemPort= 埠號來設定。
這樣,每個裝置都使用不同的本地埠,那麼可解決此問題。
(ps 此處可以使用 appium 命令列版,也可以使用桌面版)
程式碼實現如下:
import subprocess import os from Common.handle_path import appium_logs_dir class ManageAppiumServer: """ appium desktop通過命令列啟動appium服務。 不同平臺上安裝的appium,預設的appium服務路徑不一樣。 初始化時,設定appium服務啟動路徑 再根據給定的埠號啟動appium """ def __init__(self,appium_server_apth): self.server_apth = appium_server_apth # 啟動appium server服務 def start_appium_server(self,port=4723): appium_log_path = os.path.join(appium_logs_dir,"appium_server_{0}.log".format(port)) command = "node {0} -p {1} -g {2} " "--session-override " "--local-timezone " "--log-timestamp & ".format(self.server_apth, port, appium_log_path) subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,shell=True).communicate() # 關閉appium服務 @classmethod def stop_appium(cls,pc,post_num=4723): '''關閉appium服務''' if pc.upper() == 'WIN': p = os.popen(f'netstat -aon|findstr {post_num}') p0 = p.read().strip() if p0 != '' and 'LISTENING' in p0: p1 = int(p0.split('LISTENING')[1].strip()[0:4]) # 獲取程序號 os.popen(f'taskkill /F /PID {p1}') # 結束程序 print('appium server已結束') elif pc.upper() == 'MAC': p = os.popen(f'lsof -i tcp:{post_num}') p0 = p.read() if p0.strip() != '': p1 = int(p0.split('n')[1].split()[1]) # 獲取程序號 os.popen(f'kill {p1}') # 結束程序 print('appium server已結束')
在使用 pytest 執行用例時,是通過 pytest.main()會自動收集所有的用例,並自動執行生成結果。
這種情況下,appium 對談的啟動資訊是在程式碼當中給定的。
以上模式當中,只會讀取一個裝置的啟動資訊,並啟動與裝置的對談。
雖然 fixture 有引數可以傳遞多個裝置啟動資訊,但它是序列執行的。
需要解決的問題的是:
解決方案:
首先需要在 conftest.py 新增命令列選項,命令列傳入引數”--cmdopt“。
用例如果需要用到從命令列傳入的引數,就呼叫 cmdopt 函數。
def pytest_addoption(parser): parser.addoption( "--cmdopt", action="store", default="{platformName:'Android',platformVersion:'5.1.1'}", help="my devices info" ) @pytest.fixture(scope="session") def cmdopt(request): return request.config.getoption("--cmdopt") @pytest.fixture def start_app(cmdopt): device = eval(cmdopt) print("開始與裝置 {} 進行對談,並執行測試用例 !!".format(device["caps"]["deviceName"])) driver = start_appium_session(device) yield driver driver.close_app() driver.quit()
定義一個 main.py。
此方法主要是:接收裝置啟動引數,通過 pytest.main 去收集並執行用例。
# 根據裝置啟動資訊,通過pytest.main來收集並執行用例。 def run_cases(device): """ 引數:device為裝置啟動引數。在pytest.main當中,傳遞給--cmdopt選項。 """ print(["-s", "-v", "--cmdopt={}".format(device)]) reports_path = os.path.join(reports_dir,"test_result_{}_{}.html".format(device["caps"]["deviceName"], device["port"])) pytest.main(["-s", "-v", "--cmdopt={}".format(device), "--html={}".format(reports_path)] )
# 第一步:從裝置池當中,獲取當前連線的裝置。若裝置池為空,則無裝置連線。 devices = devices_pool() # 第二步:若裝置池不為空,啟動appium server.與裝置個數對應。起始server埠為4723,每多一個裝置,埠號預設+4 if devices and platform_name and appium_server_path: # 建立執行緒池 T = ThreadPoolExecutor() # 範例化appium服務管理類。 mas = ManageAppiumServer(appium_server_path) for device in devices: # kill 埠,以免佔用 mas.stop_appium(platform_name,device["port"]) # 啟動appium server task = T.submit(mas.start_appium_server,device["port"]) time.sleep(1) # 第三步:若裝置池不為空,在appium server啟動的情況下,執行app自動化測試。 time.sleep(15) obj_list = [] for device in devices: index = devices.index(device) task = T.submit(run_cases,device) obj_list.append(task) time.sleep(1) # 等待自動化任務執行完成 for future in as_completed(obj_list): data = future.result() print(f"sub_thread: {data}") # kill 掉appium server服務,釋放埠。 for device in devices: ManageAppiumServer.stop_appium(platform_name, device["port"])
到此這篇關於pytest多執行緒與多裝置並行appium的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45