poium测试库之JavaScript API封装原理

poium一直我在维护的一个开源项目,它的定位是以极简的方式在自动化项目中Page Objects设计模式。我在以前的文章中也有介绍。css

本篇文章主要介绍一个JavaScript元素操做的封装原理。python

为何要封装JavaScript的API?git

由于有些场景下Selenium提供的API并不能知足咱们需求。好比,滑动浏览滚动条,控制元素的显示/隐藏,日历控件的操做等,均可以经过JavaScrip实现,并且Selenium为咱们提供了 execute_script()方法能够用来运行JavaScrip脚本。github

旧的设计思路

先看旧的设计代码和调用。web

# =====封装代码======
class Page(object):

    def __init__(self, driver):
        self.driver = driver

    def set_text(self, css_selector, value):
        """
        JavaScript API, Only support css positioning
        Simulates typing into the element.
        """
        js = """var elm = document.querySelector("{css}");
                    elm.style.border="2px solid red";
                    elm.value = "{value}";""".format(css=css_selector(), value=value)
        self.driver.execute_script(js)

    def click(self, css_selector):
        """
        JavaScript API, Only support css positioning
        Click element.
        """
        js = """var elm = document.querySelector("{css}");
                   elm.style.border="2px solid red";
                   elm.click();""".format(css=css_selector())
        self.driver.execute_script(js)


class CSSElement(object):

    def __init__(self, css):
        self.css = css

    def __call__(self):
        return self.css


# =======调用代码==============
from selenium import webdriver

class baiduPage(Page):
    search_input = CSSElement("#kw")
    search_button = CSSElement("#su")


dr = webdriver.Chrome()
dr.get("http://www.baidu.com")
page = baiduPage(dr)
page.set_text(page.search_input, "poium")
page.click(page.search_button)

dr.close()

若是你看不懂上面的封装代码的话,能够重点看下面的调用代码,针对元素的点击和输入。设计模式

page.set_text()
page.click()

表示操做的方法,在Page类中实现。学习

page.search_input
page.search_button

表示操做的对象,在Page的继承类baiduPage中定义。设计

page.set_text(page.search_input, "poium")
page.click(page.search_button)

操做的动做操做的对象 都是以 page. 调用,万一我要操做的对象也命名为 click 那不就和操做的动做 傻傻分不清楚了, 因此,这样的语法不是很怪么?code

因此,这个问题一直困扰我挺久的,我一直没想到更好的设计。orm

新的设计思路

直到前几天又从新学习了Python的 __get____set__ 内置方法,才把这个问题解决。

# =====封装代码======
class Page(object):

    def __init__(self, driver):
        self.driver = driver


class CSSElement(object):

    driver = None

    def __init__(self, css):
        self.css = css

    def __get__(self, instance, owner):
        if instance is None:
            return None
        global driver
        driver = instance.driver
        return self

    def set_text(self, value):
        global driver
        driver.execute_script("""var elm = document.querySelector("{css}");
                    elm.style.border="2px solid red";
                    elm.value = "{value}";""".format(css=self.css, value=value))

    def click(self):
        global driver
        driver.execute_script("""var elm = document.querySelector("{css}");
                   elm.style.border="2px solid red";
                   elm.click();""".format(css=self.css))


# =======调用代码==============
from selenium import webdriver

class baiduPage(Page):
    search_input = CSSElement("#kw")
    search_button = CSSElement("#su")


dr = webdriver.Chrome()
dr.get("http://www.baidu.com")
page = baiduPage(dr)
page.search_input.set_text("poium")
page.search_button.click()

dr.close()

若是看不懂封装代码的话,直接看调用代码。

page.search_input.set_text("poium")
page.search_button.click()

page 表示页面; search_input 表示页面上的某个对象; set_text() 表示对象的动做。

这样的语法是否是要比前面好了不少?而保持了与Selenium API 封装的语法一致性。

项目地址:https://github.com/defnngj/poium

作开源项目的生活就是这么朴实无华,且有趣!

相关文章
相关标签/搜索