poium测试库之JavaScript API封装原理
- 2019 年 10 月 3 日
- 筆記
poium一直我在维护的一个开源项目,它的定位是以极简的方式在自动化项目中Page Objects设计模式。我在之前的文章中也有介绍。
本篇文章主要介绍一个JavaScript元素操作的封装原理。
为什么要封装JavaScript的API?
因为有些场景下Selenium提供的API并不能满足我们需求。比如,滑动浏览滚动条,控制元素的显示/隐藏,日历控件的操作等,都可以通过JavaScrip实现,而且Selenium为我们提供了 execute_script()
方法可以用来运行JavaScrip脚本。
旧的设计思路
先看旧的设计代码和调用。
# =====封装代码====== 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
那不就和操作的动作 傻傻分不清楚了, 所以,这样的语法不是很怪么?
所以,这个问题一直困扰我挺久的,我一直没想到更好的设计。
新的设计思路
直到前几天又重新学习了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
做开源项目的生活就是这么朴实无华,且有趣!