Appium 在 PO 模式中,driver 如何通过 basePage 在各个 testcase 中传递?

醋精测试媛 · October 15, 2020 · Last by 木有鱼丸 replied at October 17, 2020 · 2696 hits

如果是 unittest+python+pageobject+appium,如何让 driver 在各个 testcase 传递呢?
目前的想法是是使用可以在各个 py 文件间中传递的全局变量,但是总感觉不太好。basepage 是这样的:

class BasePage(object):
    """作为父类,包含driver成员变量,用于标识WebDriver,以便在子类中定位页面元素"""

    # 初始化
    def __init__(self, driver=None):
        self.driver = driver

在一个新的文件中设置了一个全局变量:

def init():
    global global_dict
    global_dict = {}


def set_value(name, value):
    global_dict[name] = value


def get_value(name):
    try:
        return global_dict[name]
    except KeyError:
        return None

在 testcase 中通过 get_value 取出来
在 start app 的 testcase 中 set_value 把 webdriver set 进去

共收到 11 条回复 时间 点赞

就是初始化的时候,传入 driver 实栗

我是这么搞的

class Run:
driver = Run()

class BasePage:
    def __init__(self, driver: WebDriver):
        self.driver = driver

class TestDemo:
    @classmethod
    def setup_class(cls):
        # run里面的driver
        cls.driver = driver

恒温 回复

大佬,错别字啊😂

全局使用 driver 不好吧,中间没有 driver 的获取跟释放么?
如果用 pytest 倒是很容易处理,可以很容易做全局变量,unittest 没尝试过😅

404铁头娃 回复

是用一个专门的类管理 driver 吗,如:

class driver:
    def __init__(self, driver: None):
        self.driver = driver
    def run(self):
        return self.driver
    def quit(self):
        self.driver.quit()

但是这样的话,每次初始化这个类都会初始化一次 driver
而且如果在 basePage 里面每次默认传入 webDriver,当我在一个 testcase 中初始化一个其他的 page 类,都会传入一个新的 webdriver,即重新打开 app 一次。

恒温 回复

请问在哪里初始化的时候呢,driver 如何在各个 py 文件之间传递呢

我们用的 pytest,在 conftest 里先初始化 driver

@pytest.fixture(scope='function')
def driver():
    # setUp
    get_driver = DriverConfig().driver_config()

    yield get_driver
    # tearDown
    LoginPage().logout(get_driver)
    get_driver.quit()

然后在测试用例里传入 driver

class TestAppEngineDF001:
    @user2e
    @pytest.mark.needUI
    @allure.feature("AppEngine")
    @allure.story("AppEngine.DF")
    def test_df_001(self, driver):
        # 用例名称
        case_name = '/autotest/appengine/DF/001'

用例里再调用 page 类,driver 是传递下去的

with allure.step("2、点击添加按钮"):
    ViewPage().view_click_operation_button(driver, '添加')

一直传到 selenium 的二次封装那部分.

def element_click(self, driver, locate_type, locator_expression, wait_for_locate_type=None,
                  wait_for_locator_expression=None, wait_for_disappear_locate_type=None,
                  wait_for_disappear_locator_expression=None, timeout=30):
    """
    元素点击
    :param driver: 浏览器驱动
    :param locate_type: 定位方式类型
    :param locator_expression: 定位表达式
    :param wait_for_locate_type: 等待元素出现的元素定位方式类型
    :param wait_for_locator_expression: 等待元素出现的元素定位表达式
    :param wait_for_disappear_locate_type:等待元素消失的元素定位方式类型
    :param wait_for_disappear_locator_expression:等待元素消失的元素定位表达式
    :param timeout:超时时间
    :return:
    """
    # 元素要可见
    element = self.element_visibility_appear(driver=driver, locate_type=locate_type,
                                             locator_expression=locator_expression,
                                             timeout=timeout)
    try:
        # 点击元素
        element.click()
    except(StaleElementReferenceException, ENI_Exception):
        self.wait_for_ready_state_complete(driver=driver)
        time.sleep(0.05)
        element = self.element_visibility_appear(driver=driver, locate_type=locate_type,
                                                 locator_expression=locator_expression,
                                                 timeout=timeout)
        element.click()
    except Exception as e:
        print("页面出现异常,元素不可点击", e)
        return False

    try:
        # 点击元素后的元素出现或元素消失
        self.element_visibility_appear(driver, wait_for_locate_type, wait_for_locator_expression)
        self.element_visibility_disappear(driver, wait_for_disappear_locate_type,
                                          wait_for_disappear_locator_expression)
    except Exception as e:
        print("等待元素消失或出现失败", e)
        return False
    return True

最方便的方法就是用一个 单例模式 初始化 driver 解决

run 类我用来启动程序,跳转每个 page ; 每个 case 都导入一次 run 里面的 driver;这样不会重新打开 app

class Run:
    def __init__(self):
        logger.info(f"开始启动应用")
        self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
    # 关闭程序
    def close(self):
        logger.info(f"执行关闭应用")
        self.driver.quit()
driver = Run()
404铁头娃 回复

结合您和楼上的评论,我好像有点思路了,我先去试试。

[Topic was deleted] 中提及了此贴 17 Oct 00:29

unittest 可以定义实例化只启动一次

醋精测试媛 关闭了讨论 19 Oct 14:42
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up