Appium 並發多進程基於 Pytest框架


前言:

 之前通過重寫unittest的初始化方法加入設備參數進行並發,實現了基於unittest的appium多設備並發,但是考慮到unittest的框架實在過於簡陋,也不方便后期的Jenkins的持續集成,所以想換一個框架來使用。

那么通過調研,pyhon+pytest+allure 這套框架很不錯,pytest是一個單元測試框架,他可以集成很多插件,包括出錯重試,參數化,等。在此特別是基於他的allure插件,能夠和Jenkins完美兼容,生成美觀強大的測試報告。

 

改造思路:

pytest框架和unittest框架明顯不同,通過命令行啟動,讀取響應目錄下的test開頭的文件,進行執行用例。

而unittest卻是通過將用例加載到TestSuite中,運行隨測試集來執行用例

所以這邊多進程就要換一種思路進行了。

基於pytest的結構和運行方式,那么思路如下:

運行方式:

1. pytest目錄下會先加載conftest.py運行。

2. 該目錄下加載test開頭的py文件

3. 加載文件中Test開頭的類

4. 加載Test類下test開頭的方法

5. 通過命令行pytest.main([1, 2 ,3])帶入1 2 3參數進行運行

解決思路:

1. 通過命令行把不同設備的參數傳遞給conftest.py

2. conftest中,使用傳遞過來的設備參數,連接設備到appium,並生成driver對象

3. 在各自的測試類和測試方法中,調用driver對象,進行測試操作

4. 生成allure測試報告

實現:

1. 通過命令行傳遞參數:

run中的設備池:

def devices_Pool():
    devices_list = []
    for i in range(0, len(getDevices())):
        _initApp = {}
        _initCaps = {}
        _initApp["devices"] = getDevices()[i]
        _initCaps["deviceName"] = getDevices()[i]
        _initCaps["platformVersion"] = getPhoneInfo(devices=_initCaps["deviceName"])["release"]
        _initCaps["platformName"] = "Android"
        _initApp["port"] = str(random.randint(4700, 4900))
        _initApp["bport"] = str(random.randint(4700, 4900))
        _initApp["systemPort"] = str(random.randint(4700, 4900))
        _initCaps["automationName"] = "UiAutomator2"
        _initCaps["appPackage"] = 'cn.vsx.vc'
        _initCaps["appActivity"] = '.activity.RegistActivity'
        _initApp["Caps"] = _initCaps
        devices_list.append(_initApp)
    print(len(getDevices()))
    print(len(devices_list))
    return devices_list

 

run中,多進程調用啟動命令行,並傳遞參數:

def runnerPool(device_list):
    getdevice = getDevices()
    with ProcessPoolExecutor(len(getdevice)) as pool:
        pool.map(runPytest, device_list)


def runPytest(device):
    print(f"cmdopt is {device}")
    report = f"report-{device['Caps']['deviceName']}".split(":", 1)[0]
    try:
        os.system(f"del /s /q E:\\appium-pytest\\{report}")
        time.sleep(1)
        os.system(f"rd /s /q E:\\appium-pytest\\{report}")
        time.sleep(1)
        print(f"{report} report has deleted")
    except:
        print("no directory existed")
    finally:
        print(f"pool run device is {device['devices']}")
        pytest.main(["../TestCases/", f"--cmdopt={device}", "--alluredir", f"../{report}/xml"])
        time.sleep(1)
        os.system(f"allure generate ../{report}/xml -o ../{report}/html")

 

conftest文件中,獲取命令行傳遞過來的參數:

def pytest_addoption(parser):
    parser.addoption("--cmdopt", action="store", default="device", help="None")

@pytest.fixture(scope="session")
def cmdopt(request):
    return request.config.getoption("--cmdopt")

 

conftest中通過傳遞的參數,生成連接對象:

@pytest.fixture(scope="session")
def connectDevice(cmdopt):
    device = eval(cmdopt)
    device_caps = {}
    device_caps["platformVersion"] = getPhoneInfo(device["Caps"]["deviceName"])["release"]
    device_caps["platformName"] = "Android"
    device_caps["automationName"] = "UiAutomator2"
    device_caps["deviceName"] = device["Caps"]['deviceName']
    device_caps["udid"] = device["Caps"]['deviceName']
    device_caps["appPackage"] = "cn.vsx.vc"
    device_caps["appActivity"] = ".activity.RegistActivity"
    device_caps["noReset"] = True
    device_caps["noSign"] = True
    device_caps["unicodeKeyboard"] = True
    device_caps["resetKeyboard"] = True
    device_caps["systemPort"] = int(device["systemPort"])
    remote = "http://127.0.0.1:" + str(device["port"]) + "/wd/hub"
    print(f"wo shi pytest {device_caps}")
    driver = webdriver.Remote(remote, device_caps)
    return driver

 

測試用例中,使用對象來進行操作:

class Test_groupCall():
    @allure.feature("group_call")
    @allure.story("login")
    def test001_login(self, connectDevice):
        '''登入選擇單位'''
        WebDriverWait(connectDevice, 10).until(
            lambda x: x.find_element_by_xpath(
                "//android.widget.TextView[contains(@text, '選擇單位')]").is_displayed())  # 驗證等待10秒超時
        x = connectDevice.get_window_size()['width']  # 獲取當前屏幕寬
        y = connectDevice.get_window_size()['height']  # 獲取當前屏幕高
        a, b = 170 / 768, 790 / 1184  # 選擇單位222系數
        connectDevice.find_element_by_xpath("//android.widget.TextView[contains(@text, '選擇單位')]").click()

 

最后:

多設備連接時,一定要注意給每個desired_caps中加入每個設備自己的systemPort,否則會連接不上多設備,至此改造成功,最后生成的報告也讓人滿意:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM