來自APP Android端自動化測試初學者的筆記,寫的不對的地方大家多多指教哦
一、啟動appium服務器
1.通過命令行窗口啟動單個appium服務器
appium -- 直接打開默認的4723端口號
appium -p 4723 -- 使用-p來啟動固定端口號的appium服務器
2.通過命令行窗口啟動多個appium服務器
appium -p 4723
appium -p 4726
二、啟動多個設備
1.在yaml文件配置Capability參數(shù)
desired_caps.yaml
platformName: Android
platformVersion: '9'
deviceName: U4AIUKFAL7W4MJLR
appPackage: com.sina.weibo
appActivity: com.sina.weibo.SplashActivity
automationName: UiAutomator2
autoGrantPermissions: True
noReset: True
url: 127.0.0.1
注意:
- 手機系統(tǒng)版本號屬于字符串格式,需要加''引號
- url為appium服務器的地址
- 啟動多個設備需要啟動多個appium服務,所以這邊不設置端口號
2.代碼實現(xiàn)
from time import ctime
import yaml
from appium import webdriver
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
with open(r"E:\\\\study\\\\Fork\\\\WeiboDemo\\\\Weibo\\\\config\\\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
def multi_app_start(udid, port):
desired_caps = {'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
}
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
driver.implicitly_wait(10)
return driver
# 測試函數(shù),在實際運行過程中可以注釋
if __name__ == '__main__':
multi_app_start(devices_list[0], 4723)
multi_app_start(devices_list[1], 4725)
注意:
- 需要開啟兩個appium服務,且端口號不能一樣
- 連接的設備主要根據(jù)udid連接,而不是根據(jù)yaml文件中的deviceName,所以在yaml文件中的deviceName可以隨意設置
- ctime()表示當前時間
- 以上為成功啟動一個后才會啟動另外一個,不是同步啟動兩個設備
最后運行結果為:

image.png
對以上代碼封裝成類:
class MultiDevices:
driver: webdriver = None
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
def appium_desire(self, udid, port):
with open(r"E:\\study\\Fork\\WeiboDemo\\Weibo\\config\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
desired_caps = {'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
}
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
self.driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
self.driver.implicitly_wait(10)
return self.driver
# 測試函數(shù),在實際運行中可以注釋
if __name__ == '__main__':
mas1 = MultiDevices()
mas2 = MultiDevices()
mas1.appium_desire(MultiDevices.devices_list[0], 4723)
mas2.appium_desire(MultiDevices.devices_list[1], 4725)
三、多進程并發(fā)啟動設備
- 多進程中,同一個變量,各自有拷貝一份存在于每個進程中,互不影響
- 多線程中,所有變量都由所有線程共享,任意一個比那輛都可以被任何一個線程修改,因此,線程之間共享數(shù)據(jù)最大的危險在于多個線程同時改一個變量,容易把內(nèi)容改亂了
所以我使用的是多進程并發(fā)啟動設備
yaml文件同上,代碼實現(xiàn)如下:
import multiprocessing
from time import ctime
import yaml
from appium import webdriver
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
with open(r"E:\\\\study\\\\Fork\\\\WeiboDemo\\\\Weibo\\\\config\\\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
def multi_app_start(udid, port):
desired_caps = {'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
}
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
driver.implicitly_wait(10)
return driver
# 構建desired進程組
desired_process = []
# 加載desired進程
for i in range(len(devices_list)):
port = 4723 + 2 * i
# target="調(diào)用的方法",args="傳入的參數(shù)"
desired = multiprocessing.Process(target=multi_app_start, args=(devices_list[i], port))
desired_process.append(desired)
if __name__ == '__main__':
# 啟動多設備執(zhí)行測試
for desired in desired_process:
desired.start()
# 等所有進程結束后關閉
for desired in desired_process:
desired.join()
結果同上,但同時啟動,控制臺輸出的日志中時間一致
對以上代碼封裝成類
class MultiDevicesSync:
driver: webdriver = None
devices_list = ['U4AIUKFAL7W4MJLR', 'U4AIUKFAL7W4MHUHUDS']
def multi_devices_sync(udid, port):
with open(r"E:\\study\\Fork\\WeiboDemo\\Weibo\\config\\desired_caps.yaml", 'r') as file:
data = yaml.load(file, Loader=yaml.FullLoader)
desired_caps = {'platformName': data['platformName'],
'platformVersion': data['platformVersion'],
'deviceName': data['deviceName'],
'udid': udid,
'appPackage': data['appPackage'],
'appActivity': data['appActivity'],
'automationName': data['automationName'],
'autoGrantPermissions': data['autoGrantPermissions'],
'noReset': data['noReset']
}
print('appium port:%s start run %s at %s' % (port, udid, ctime()))
driver = webdriver.Remote('http://' + str(data['url']) + ':' + str(port) + '/wd/hub', desired_caps)
driver.implicitly_wait(10)
return driver
# 構建desired進程組
desired_process = []
# 加載desired進程
for i in range(len(devices_list)):
port = 4723 + 2 * i
# target="調(diào)用的方法",args="傳入的參數(shù)"
desired = multiprocessing.Process(target=multi_devices_sync, args=(devices_list[i], port))
desired_process.append(desired)
if __name__ == '__main__':
multi_devices_sync = MultiDevicesSync()
# 啟動多設備執(zhí)行測試
for desired in multi_devices_sync.desired_process:
desired.start()
# 等所有進程結束后關閉
for desired in multi_devices_sync.desired_process:
desired.join()
補充:
1.進程和線程的區(qū)別?
進程是計算機中的程序關于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結構的基礎。
線程有時也被稱為輕量級進程,是程序執(zhí)行流的最小單元。線程是進程中的一個實體,一個進程可以包含多個線程,但是線程不能包含多個進程。線程自己不擁有系統(tǒng)資源,在單個程序中同時運行多個線程完成不同的工作,成為多線程。
區(qū)別:
數(shù)據(jù)空間的分配,子進程和父進程有不同的代碼和數(shù)據(jù)空間,而多個線程則共享數(shù)據(jù)空間,每個線程有自己的執(zhí)行堆棧和程序計數(shù)器為其執(zhí)行上下文。
可以將進程看成是一個工廠,多個進程就是多個工廠;把線程看成是工廠里面的流水線,一個工廠中可以同時有多個流水線。