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

醋精测试媛 · October 15, 2020 · Last by 卖鱼丸的白帽 replied at October 17, 2020 · 1191 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:
@pytest.mark.appengine
@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铁头娃 回复

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

柒意 关于 ui 自动化测试 driver 疑问? 中提及了此贴 17 Oct 00:29

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

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