51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1481|回复: 1
打印 上一主题 下一主题

【转】在Python中实现PageFactory模式

[复制链接]
  • TA的每日心情
    擦汗
    昨天 09:02
  • 签到天数: 1042 天

    连续签到: 4 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2016-10-21 14:39:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    关于 PageFactory 的概念主要是Java中内置了PageFactory类。
    1. 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中的元素定位是这样的:

    1. find_element_by_id("kw")
    2. find_element_by_xpath("//*[@id='kw']")
    复制代码
    或者是这样的:
    1. from selenium.webdriver.common.by import By

    2. find_element(By.ID,"kw")
    3. find_element(By.XPATH,"//*[@id='kw']")
    复制代码
    通过PageFactory 模式的实现可以把元素定位变成这样的:
    1. from pageobject_support import callable_find_by as find_by

    2. find_by(id_="kw")
    3. find_by(xpath="//*[@id='kw']")
    复制代码
    别看小小的改动,它其实使代码更容易的阅读和理解。



    核心实现就是pageobject_support.py文件:

    1. __all__ = ['cacheable', 'callable_find_by', 'property_find_by']

    2. def cacheable_decorator(lookup):
    3.     def func(self):
    4.         if not hasattr(self, '_elements_cache'):
    5.             self._elements_cache = {} # {callable_id: element(s)}
    6.         cache = self._elements_cache

    7.         key = id(lookup)
    8.         if key not in cache:
    9.             cache[key] = lookup(self)
    10.         return cache[key]
    11.         
    12.     return func

    13. cacheable = cacheable_decorator

    14. _strategy_kwargs = ['id_', 'xpath', 'link_text', 'partial_link_text',
    15.                     'name', 'tag_name', 'class_name', 'css_selector']

    16. def _callable_find_by(how, using, multiple, cacheable, context, driver_attr, **kwargs):
    17.     def func(self):
    18.         # context - driver or a certain element
    19.         if context:
    20.            ctx = context() if callable(context) else context.__get__(self) # or property
    21.         else:
    22.            ctx = getattr(self, driver_attr)

    23.         # 'how' AND 'using' take precedence over keyword arguments
    24.         if how and using:
    25.             lookup = ctx.find_elements if multiple else ctx.find_element
    26.             return lookup(how, using)

    27.         if len(kwargs) != 1 or kwargs.keys()[0] not in _strategy_kwargs :
    28.             raise ValueError(
    29.                 "If 'how' AND 'using' are not specified, one and only one of the following "
    30.                 "valid keyword arguments should be provided: %s." % _strategy_kwargs)

    31.         key = kwargs.keys()[0]; value = kwargs[key]
    32.         suffix = key[:-1] if key.endswith('_') else key # find_element(s)_by_xxx
    33.         prefix = 'find_elements_by' if multiple else 'find_element_by'
    34.         lookup = getattr(ctx, '%s_%s' % (prefix, suffix))
    35.         return lookup(value)

    36.     return cacheable_decorator(func) if cacheable else func

    37. def callable_find_by(how=None, using=None, multiple=False, cacheable=False, context=None, driver_attr='_driver', **kwargs):
    38.     return _callable_find_by(how, using, multiple, cacheable, context, driver_attr, **kwargs)

    39. def property_find_by(how=None, using=None, multiple=False, cacheable=False, context=None, driver_attr='_driver', **kwargs):
    40.     return property(_callable_find_by(how, using, multiple, cacheable, context, driver_attr, **kwargs))
    复制代码
    然后,我再帖一下具体的例子:
    1. from pageobject_support import callable_find_by as find_by
    2. from selenium import webdriver

    3. class BaiduSearchPage(object):

    4.     def __init__(self, driver):
    5.         self._driver = driver

    6.     search_box = find_by(id_="kw")
    7.     search_button = find_by(id_='su')

    8.     def search(self, keywords):
    9.         self.search_box().clear()
    10.         self.search_box().send_keys(keywords)
    11.         self.search_button().click()


    12. if __name__ == '__main__':
    13.     driver = webdriver.Chrome()
    14.     driver.get("https://www.baidu.com")
    15.     BaiduSearchPage(driver).search("selenium")
    16.     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模式把驱动的创建做了封装,感兴趣可以了解一下。



    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2019-12-31 08:59
  • 签到天数: 975 天

    连续签到: 1 天

    [LV.10]测试总司令

    2#
    发表于 2016-11-1 12:23:51 | 只看该作者
    支持乱码,,po和pf了解下
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-8 14:50 , Processed in 0.061487 second(s), 22 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表