TA的每日心情 | 无聊 7 小时前 |
---|
签到天数: 1043 天 连续签到: 1 天 [LV.10]测试总司令
|
关于 PageFactory 的概念主要是Java中内置了PageFactory类。
- import org.openqa.selenium.support.PageFactory;
复制代码 例子,http://libin0019.iteye.com/blog/1260090
Python(Selenium)中没有这个类。 PageFactory 的概念和Page Object应该类似,属于一种设计模式。所以并不局限于语言及场景。于是,好奇,既然Java有,那Python也应该有类似的玩法。还真让我给找到了类似的实现。
原文在此:https://jeremykao.wordpress.com/ ... -pattern-in-python/
于是,就借助谷歌翻译加代码运行,弄懂了这哥们想要利用PageFactory 模式实现个什么东西,为了便于你的理解,我这里搬运过来给下结论。
selenium in python中的元素定位是这样的:
- find_element_by_id("kw")
- find_element_by_xpath("//*[@id='kw']")
复制代码 或者是这样的:
- from selenium.webdriver.common.by import By
- find_element(By.ID,"kw")
- find_element(By.XPATH,"//*[@id='kw']")
复制代码 通过PageFactory 模式的实现可以把元素定位变成这样的:
- from pageobject_support import callable_find_by as find_by
- find_by(id_="kw")
- find_by(xpath="//*[@id='kw']")
复制代码 别看小小的改动,它其实使代码更容易的阅读和理解。
核心实现就是pageobject_support.py文件:
- __all__ = ['cacheable', 'callable_find_by', 'property_find_by']
- def cacheable_decorator(lookup):
- def func(self):
- if not hasattr(self, '_elements_cache'):
- self._elements_cache = {} # {callable_id: element(s)}
- cache = self._elements_cache
- key = id(lookup)
- if key not in cache:
- cache[key] = lookup(self)
- return cache[key]
-
- return func
- cacheable = cacheable_decorator
- _strategy_kwargs = ['id_', 'xpath', 'link_text', 'partial_link_text',
- 'name', 'tag_name', 'class_name', 'css_selector']
- def _callable_find_by(how, using, multiple, cacheable, context, driver_attr, **kwargs):
- def func(self):
- # context - driver or a certain element
- if context:
- ctx = context() if callable(context) else context.__get__(self) # or property
- else:
- ctx = getattr(self, driver_attr)
- # 'how' AND 'using' take precedence over keyword arguments
- if how and using:
- lookup = ctx.find_elements if multiple else ctx.find_element
- return lookup(how, using)
- if len(kwargs) != 1 or kwargs.keys()[0] not in _strategy_kwargs :
- raise ValueError(
- "If 'how' AND 'using' are not specified, one and only one of the following "
- "valid keyword arguments should be provided: %s." % _strategy_kwargs)
- key = kwargs.keys()[0]; value = kwargs[key]
- suffix = key[:-1] if key.endswith('_') else key # find_element(s)_by_xxx
- prefix = 'find_elements_by' if multiple else 'find_element_by'
- lookup = getattr(ctx, '%s_%s' % (prefix, suffix))
- return lookup(value)
- return cacheable_decorator(func) if cacheable else func
- def callable_find_by(how=None, using=None, multiple=False, cacheable=False, context=None, driver_attr='_driver', **kwargs):
- return _callable_find_by(how, using, multiple, cacheable, context, driver_attr, **kwargs)
- def property_find_by(how=None, using=None, multiple=False, cacheable=False, context=None, driver_attr='_driver', **kwargs):
- return property(_callable_find_by(how, using, multiple, cacheable, context, driver_attr, **kwargs))
复制代码 然后,我再帖一下具体的例子:
- from pageobject_support import callable_find_by as find_by
- from selenium import webdriver
- class BaiduSearchPage(object):
-
- def __init__(self, driver):
- self._driver = driver
- search_box = find_by(id_="kw")
- search_button = find_by(id_='su')
-
- def search(self, keywords):
- self.search_box().clear()
- self.search_box().send_keys(keywords)
- self.search_button().click()
- if __name__ == '__main__':
- driver = webdriver.Chrome()
- driver.get("https://www.baidu.com")
- BaiduSearchPage(driver).search("selenium")
- driver.close()
复制代码 同样封装了8种定位方法:
id_ (为避免与内置的关键字ID冲突,所以多了个下划线的后缀)
name
class_name
css_selector
tag_name
xpath
link_text
partial_link_text
当然,这只是PageFactory 模式的一种表现形式而已。除此之外,我还找到了另外一个PageFactory模式的例子。
https://github.com/mattfair/SeleniumFactory-for-Python
这哥们是利用PageFactory模式把驱动的创建做了封装,感兴趣可以了解一下。
|
|