Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
实现页面对象模型的Python应用程序_Python_Selenium_Appium_Python Appium - Fatal编程技术网

实现页面对象模型的Python应用程序

实现页面对象模型的Python应用程序,python,selenium,appium,python-appium,Python,Selenium,Appium,Python Appium,我正试图用appium实现“By”和“key”,就像我在selenium上所做的那样 在selenium上,我可以这样做: 定位器 from selenium.webdriver.common.by import By class LoginPageLocators(object): HEADING = (By.CSS_SELECTOR, 'h3[class="panel-title"]') USERNAME = (By.NAME, 'username') PASSWO

我正试图用appium实现“By”和“key”,就像我在selenium上所做的那样

在selenium上,我可以这样做:

定位器

from selenium.webdriver.common.by import By

class LoginPageLocators(object):
    HEADING = (By.CSS_SELECTOR, 'h3[class="panel-title"]')
    USERNAME = (By.NAME, 'username')
    PASSWORD = (By.NAME, 'password')
    LOGIN_BTN = (By.CSS_SELECTOR, 'input[value="Login"]')
功能

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from base import Page
from locators.locators import *

class LoginPage(Page):

    def __init__(self, context):
        Page.__init__(
            self,
            context)

    def goto_login_page(self, url):
        self.open(url)

    def enter_username(self, username):
        uname = self.find_element(*LoginPageLocators.USERNAME)
        uname.send_keys(username)

    def enter_password(self, password):
        pword = self.find_element(*LoginPageLocators.PASSWORD)
        pword.send_keys(password)

    def click_login(self):
        login = self.find_element(*LoginPageLocators.LOGIN_BTN)
        login.click()

    def verify_dashboard_page(self, page):
        self.verify_page(page)
在阿皮姆有办法做到这一点吗?如果我这样做,则没有模块:

 from appium.webdriver.common.by import By
 from appium.webdriver.common.keys import Keys

我用另一种方法来定位

我有page_对象目录,其中包含应用程序页面和常规文件库页面的文件。在Base_page.py中,我包含了其他页面的一般操作方法。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
为了找到定位器的正确方法,我在同一个文件-base_page.py中创建了自定义方法。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
Get_locator_by_字符串不包含所有搜索方法。我需要一些方法

在locators文件中,我有两种方法——Android和iOS。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
要为平台选择正确的定位器,我使用平台检查方法。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
要检查此文件的当前平台,请执行以下操作:

import os
from appium import webdriver
from src import config


def get_env(key, default=None):
    return os.environ.get(key=key, default=default)


def get():
    if IS_ANDROID:
        return webdriver.Remote(
            command_executor=config.APPIUM_HOST,
            desired_capabilities=config.DESIRED_CAPS_ANDROID_RESET
        )
    else:
        return webdriver.Remote(
            command_executor=config.APPIUM_HOST,
            desired_capabilities=config.DESIRED_CAPS_ANDROID_RESET
        )


PLATFORM = get_env('PLATFORM', 'IOS')

IS_ANDROID = PLATFORM == 'ANDROID'
IS_IOS = PLATFORM == 'IOS'
以及用于设置当前测试平台的最后一个文件:

#!/usr/bin/env bash

export PLATFORM=IOS
export PLATFORM=ANDROID
APPIUM_主机和其他文件中的所需_CAPS_ANDROID_RESET/所需_CAPS_ANDROID_RESET。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
设备和我的应用程序是另一本字典


我希望我的经验能对你有所帮助

我用另一种方法来定位

我有page_对象目录,其中包含应用程序页面和常规文件库页面的文件。在Base_page.py中,我包含了其他页面的一般操作方法。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
为了找到定位器的正确方法,我在同一个文件-base_page.py中创建了自定义方法。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
Get_locator_by_字符串不包含所有搜索方法。我需要一些方法

在locators文件中,我有两种方法——Android和iOS。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
要为平台选择正确的定位器,我使用平台检查方法。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
要检查此文件的当前平台,请执行以下操作:

import os
from appium import webdriver
from src import config


def get_env(key, default=None):
    return os.environ.get(key=key, default=default)


def get():
    if IS_ANDROID:
        return webdriver.Remote(
            command_executor=config.APPIUM_HOST,
            desired_capabilities=config.DESIRED_CAPS_ANDROID_RESET
        )
    else:
        return webdriver.Remote(
            command_executor=config.APPIUM_HOST,
            desired_capabilities=config.DESIRED_CAPS_ANDROID_RESET
        )


PLATFORM = get_env('PLATFORM', 'IOS')

IS_ANDROID = PLATFORM == 'ANDROID'
IS_IOS = PLATFORM == 'IOS'
以及用于设置当前测试平台的最后一个文件:

#!/usr/bin/env bash

export PLATFORM=IOS
export PLATFORM=ANDROID
APPIUM_主机和其他文件中的所需_CAPS_ANDROID_RESET/所需_CAPS_ANDROID_RESET。例如:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ex_cond
from src.platform import PLATFORM, IS_IOS

class BasePage:

    def __init__(self, driver: webdriver) -> None:
        self._driver = driver

    def get_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        return WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))

    def get_no_element(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.invisibility_of_element_located(by), ' : '.join(by))
        if element is None:
            return 'No element found'


    def get_element_text(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        if IS_IOS:
            return element.get_attribute('label')
        else:
            return element.text

    def get_element_and_click(self, locator: str, timeout=10):
        by = get_locator_by_string(locator)
        element = WebDriverWait(self._driver, timeout).until(
            ex_cond.visibility_of_element_located(by), ' : '.join(by))
        return element.click()
def get_locator_by_string(locator_with_type):
    exploided_locator = locator_with_type.split(':', 1)
    by_type = exploided_locator[0]
    locator = exploided_locator[1]

    if by_type == 'xpath':
        return (MobileBy.XPATH, locator)
    elif by_type == 'css':
        return (MobileBy.CSS_SELECTOR, locator)
    elif by_type == 'id':
        return (MobileBy.ID, locator)
    elif by_type == 'accessibility_id':
        return (MobileBy.ACCESSIBILITY_ID, locator)
    elif by_type == 'android_uiautomator':
        return (MobileBy.ANDROID_UIAUTOMATOR, locator)
    elif by_type == 'ios_uiautomation':
        return (MobileBy.IOS_UIAUTOMATION, locator)
    elif by_type == 'ios_predicate':
        return (MobileBy.IOS_PREDICATE, locator)
    elif by_type == 'class':
        return (MobileBy.CLASS_NAME, locator)
    else:
        raise Exception(f'Cannot get type of locator. Locator 
            {locator_with_type}')
import allure
from src.config import BUNDLE_APP
from src.ui.base_page import BasePage, locator_for_platform


class AuthorPage(BasePage):

    _author_title = locator_for_platform({
        'ANDROID': 'id:%s:id/authorName' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_name'
    })

    _subscribe_button = locator_for_platform({
        'ANDROID': 'id:%s:id/subscribeBackground' % BUNDLE_APP,
        'IOS': 'accessibility_id:author_subscribe_button'
    })

    @allure.step('Press subscribe button')
    def press_subscribe_button(self):
        super().get_element_and_click(self._subscribe_button)

    @allure.step('Get subscribe button text')
    def get_subscribe_button_text(self):
        return super().get_element_text(self._subscribe_button_text)

    @allure.step('Get author\'s name text')
    def get_author_name_text(self):
        return super().get_element_text(self._author_title)
def locator_for_platform(selectors):
    return selectors.get(PLATFORM, 'Undefined Selector')
APPIUM_HOST = 'http://localhost:4445/wd/hub'

DESIRED_CAPS_IOS = {
    'platformName': 'iOS',
    'platformVersion': '13.3',
    'deviceName': 'iPhone 8',
    'automationNam': 'XCUITest',
    'app': MY_APP_IOS
}

DESIRED_CAPS_ANDROID_RESET = {
    'platformName': 'Android',
    'platformVersion': '10',
    'automationName': 'uiautomator2',
    'deviceName': DEVICES['Pixel Emulator (10.0)'],
    'app': MY_APP_ANDROID,
    'unicodeKeyboard': 'true',
    'resetKeyboard': 'true',
    'disableWindowAnimation': 'true',
    'autoWebviewTimeout': '2000',
    'clearDeviceLogsOnStart': 'true'
}
设备和我的应用程序是另一本字典

我希望我的经验能对你有所帮助