POM模式是什么
- 页面对象模型(POM)是一种设计模式,用来管理维护一组web元素集的对象库
- 在POM模式下,应用程序的每一个页面都有一个对的page class
- 每一个page class维护着该web页的元素集合操作这些元素的方法
- page class中的方法名最好根据业务场景进行
POM模式的代码目录组织示例:
POM的优势:
- POM提供了一种在UI层操作、业务流程与验证分离的模式,这使得测试代码变得更加清晰和高可读性
- 对象库与用例分离,使得我们更好的复用对象,甚至能与不同的工具进行深度结合应用
- 可复用的页面方法代码会变得更加优化
- 更加有效的命名方式使得我们更加清晰的知道方法所操作的UI元素。例如我们要回到首页,方法名命名为: gotoHomePage(),通过方法名即可清晰的知道具体的功能实现。
可以理解POM模式是一种底层、逻辑、用例的分层。
一、driver层的封装(最底层的封装base)
这一层主要是对于webdriver方法的封装,这里来举一个栗子,最常用的定位方法,使用find_element()方法通过BY类、字符串、元组三种方法传递定位类型和数据,这里我使用元组的形式(例如locator = ("id","name_box"))来传递参数
1.1定位元素方法封装
这个定位元素的公共方法中,加了很多东西;如果每次定位的时候写这些异常捕获、打印操作的话,那么程序会非常臃肿,所以需要单独提出来,每次需要定位的时候统一调用这个方法。
- 有一个入参locator,格式为(‘定位类型’,‘定位参数值’),返回我们所定位到的元素
- 加入了元素等待,并判断该元素是否存在
- 对关键信息的打印输出,方便定位监控
- 加入了异常捕获,定位失败后可以继续执行程序
def findElementNew(self, locator): '''定位到元素返回元素对象,没定位到,返回timeout异常''' # isinstance() 函数来判断一个对象是否是一个已知的类型 if not isinstance(locator, tuple): print('locator参数类型错误,必须是元祖类型:loc=("id", "value")') else: try: print("正在定位元素信息:定位方式->%s, value值->%s" % (locator[0], locator[1])) ele = WebDriverWait(self.driver, self.timeout, self.t).until(EC.presence_of_element_located(locator)) return ele except: return []
1.2封装类的初始化
对于webdriver的封装,我们要先创建一个class,这样方便我们继承调用这些封装的方法。在class中,我这里设计了一个初始化,每次调用封装的driver时,传递参数,一个必填项:driver,我这样的想法是每次引用这个封装类时,传递一个driver进来
def __init__(self, driver): self.driver = driver self.driver.maximize_window()
二、page层书写
page类在继承我们封装的webdriver后,主要写具体的操作步骤,例如输入登录名、输入登录密码、点击登录按钮等操作。
2.1继承driver类
2.2操作步骤书写
class LoginPage(Base): #继承 # 定位登录 loc_user = ('id', 'account') loc_psw = ('css selector', '[name="password"]') loc_button = ('xpath', '//*[@id="submit"]') loc_get_user = ('css selector', '#userMenu>a') loc_forget_psw_page = ('xpath', '/html/body/div/div/div[2]/p/a') def input_user(self, text=''): self.sendKeys(self.loc_user, text) def input_psw(self, text=''): self.sendKeys(self.loc_psw, text) def click_login_button(self): self.click(self.loc_button)
三、case层调用
终于到了第三层,这里我们要做的就是把page层的方法,像搭积木一样搭起来,并且连成完整的操作。
3.1使用unittest,并初始化数据
在unittest框架的基础上,主要是在setUp()方法中初始化我们的数据,例如网址、账号、driver的初始化。
3.2调用方法,完成用例
首先引用page层,然后使用page层的方法搭建case。