关于PO模型遇到的一个问题
背景:基于pytest+poium实现UI自动化
问题:先看下我们基于PO思想封装的一个页面类,每个行为我们都把它处理为一个类方法,再看用例层,传入全局browser(全局浏览器驱动实例)给类Search_baidu,执行用例的时候会报一个错误:
AttributeError: ‘NoneType’ object has no attribute ‘find_elements’
# 页面类from poium import Page, NewPageElementclass Search_baidu(Page):"""百度首页页面元素定位"""@classmethoddef input_search(cls, search_key):input_text = NewPageElement(css='input[name="wd"]', describe="输入搜索关键词")input_text.send_keys(search_key)@classmethoddef click_search(cls):click_btn = NewPageElement(css='input[class$="s_btn"]', describe="点击搜索")click_btn.click()
# 用例层"""使用poium库实现百度搜索功能"""import pytestfrom page_handle.baidu_demo.baidu_search import Search_baiduclass TestBaidu:"""百度搜素"""def test_baidu_search_case2(self, browser, baidu_url):page_baidu = Search_baidu(browser)page_baidu.get(baidu_url)page_baidu.input_search('pytest')page_baidu.click_search()
原因:基于上面报的错误,直接追踪到NewPageElement类,看下部分源码发现,NewPageElement类其实是一个数据描述符,通过get(),拿到一个browser实例,再回到我们的的页面类,NewPageElement代理非类属性,所以无法触发get(),也就无法拿到browser实例,只有代理另一个类的类属性才能触发get()
# NewPageElement类部分源码class NewPageElement(object):"""new Page element class"""def __init__(self, timeout=5, describe="undefined", index=0, **kwargs):self.timeout = timeoutself.index = indexself.desc = describeif not kwargs:raise ValueError("Please specify a locator")if len(kwargs) > 1:raise ValueError("Please specify only one locator")self.kwargs = kwargsself.k, self.v = next(iter(kwargs.items()))if self.k not in LOCATOR_LIST.keys():raise FindElementTypesError("Element positioning of type '{}' is not supported.".format(self.k))def __get__(self, instance, owner):if instance is None:return NoneBrowser.driver = instance.driverreturn selfdef __set__(self, instance, value):self.__get__(instance, instance.__class__)self.send_keys(value)def __find_element(self, elem):"""Find if the element exists."""logging.info("Browser.driver调试!!: {}".format(Browser.driver))for i in range(self.timeout):elems = Browser.driver.find_elements(by=elem[0], value=elem[1])if len(elems) == 1:logging.info("Find element: {by}={value} ".format(by=elem[0], value=elem[1]))breakelif len(elems) > 1:logging.info("Find {n} elements through: {by}={value}".format(n=len(elems), by=elem[0], value=elem[1]))breakelse:sleep(1)else:error_msg = "Find 0 elements through: {by}={value}".format(by=elem[0], value=elem[1])logging.error(error_msg)raise NoSuchElementException(error_msg)
解决问题:因为NewPageElement是数据描述符,把描述符定义为这个类的类属性,则解决问题
备注:更多关于描述符知识点见python描述符
_
设置浏览器启动语言
有时候开启浏览器需要特别的语言版本,比如,英文的,中文的。
测试时候发现,机器默认启动的是系统语言对应的浏览器,我们的被测网站的中文的,而系统是英文的,开启的浏览器就是英文的,提交的某些数据按照英文的格式提交了,导致数据报错,那么我们就需要设置浏览器启动语言。
Chrome 需要通过ChromeOptions来解决,设置如下参数(—lang=zh-CN):
def web_driver():"""定义浏览器驱动:return:"""driver = Nonechrome_options = CH_Options()if Config.DRIVER_TYPE == 'chrome':# 界面模式chrome_options.add_argument('--ignore-certificate-errors')driver = webdriver.Chrome(options=chrome_options)elif Config.DRIVER_TYPE == 'chrome_headless':# 无头模式chrome_options.add_argument('--headless')chrome_options.add_argument('--lang=zh-CN') # 设置chrome启动语言为中文chrome_options.add_argument('--disable-gpu')chrome_options.add_argument('--window-size=1680x1050')chrome_options.add_argument('--ignore-certificate-errors')driver = webdriver.Chrome(options=chrome_options)else:raise NameError("driver 浏览器驱动定义错误!")driver.maximize_window()driver.implicitly_wait(10)return driver
记一次关于如何启动麦克风权限

chrome启动参数中增加 use-fake-device-for-media-stream、use-fake-ui-for-media-stream
def web_driver():"""定义浏览器驱动:return:"""chrome_options = CH_Options()if Config.DRIVER_TYPE == 'chrome':# 界面模式chrome_options.add_argument('--ignore-certificate-errors') # 忽略与证书相关的错误chrome_options.add_argument("allow-file-access-from-files") # 允许打开本地文件# --use-fake-device-for-media-stream 使用假设备进行MediaStream替换实际的摄像头和麦克风# --use-fake-ui-for-media-stream 通过选择媒体流的默认设备来绕过媒体流信息量。与--use-fake-device-for-media-stream一起使用chrome_options.add_argument("use-fake-device-for-media-stream")chrome_options.add_argument("use-fake-ui-for-media-stream")driver = webdriver.Chrome(options=chrome_options)elif Config.DRIVER_TYPE == 'chrome_headless':# 无头模式chrome_options.add_argument('--headless')chrome_options.add_argument('--lang=zh-CN') # 设置chrome启动语言为中文chrome_options.add_argument('--disable-gpu')chrome_options.add_argument('--window-size={}'.format(screen_size()))chrome_options.add_argument('--ignore-certificate-errors')driver = webdriver.Chrome(options=chrome_options)logger.info("当前系统分辨率为{}".format(screen_size()))else:raise NameError("driver 浏览器驱动定义错误!")driver.maximize_window()driver.implicitly_wait(10)return driver
