前言:做selenium自动化,肯定是要学习po模式的,它会让你的代码实现低耦合,数据与结构分离。
Page Object Model (POM)“页面对象模型”,讲元素定位和基本方法封装在一个页面对象中,只对外提供必要的操作接口
如何设计pom?
①首先要有一个BasePage类,用来封装浏览器基本操作,一些公共方法和关键字
②各个Page类是封装它这个页面的一些元素操作和方法,以及所需的参数值
③TestCase就是用unittest执行用例,并且加入断言判断用例是否成功
下面是我画的流程图
BasePage.py 这个类是封装浏览器基本操作方法的,比如driver,找寻元素定位,输入框输入,点击事件等,注意带的参数,包括找寻方法用显式等待
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BasePage():
'''
封装浏览器基本操作
公共方法:等待时间,截图,点击,日志,浏览器所有操作
需求:任何点击,自动去加等待时间
关键字驱动:
公共方法关键字:
业务关键字:操作经常绑定在一起的,封装成关键字
'''
def __init__(self,driver):
self.driver=driver
def find_ele(self,loc):
'''
找元素的方法,加上显式等待时间
:param loc:
:return: ele:webdriver对象
'''
try:
ele=WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc))
except Exception as e:
print(e)
return ele
def my_send_keys(self,loc,value):
'''
输入方法
:param loc: 元素的定位
:param value: 输入的值
:return:
'''
self.find_ele(loc).send_keys(value)
def my_click(self,loc):
'''
点击方法
:param loc: 元素的定位
:return:
'''
self.find_ele(loc).click()
LoginPage.py 是登陆页面的一个类,主要是登陆的时候所需要的元素定位方法,这里用到的是By方式,自己可以决定是用ID,还是XPATH,还是CLASSNAME,最后封装成一个login方法
from selenium.webdriver.common.by import By
from po.BasePage import BasePage
class LoginPage(BasePage):
username=(By.ID,'userName')
pwd=(By.ID,'passWord')
login_button=(By.XPATH,'/html/body/div/div/div/div[2]/div/form/div[4]/div/div/span/button')
def username_input(self,value):
self.my_send_keys(self.username,value)
def pwd_input(self,value):
self.my_send_keys(self.pwd,value)
def click_button(self):
self.my_click(self.login_button)
def login(self,username,password):
'''
登陆方法
:param username: 用户名
:param password: 密码
:return:
'''
self.username_input(username)
self.pwd_input(password)
self.click_button()
这只是登陆页面,还有首页啊,创建页面啊,都可以封装自己的class类
最后是testcase用例执行,注意这个类是怎么使用LoginPage里的参数的
首先是要继承LoginPage
因为在LoginPage.py文件里已经直接封装了登陆方法,所以可以直接调用login方法就行
在没有封装login之前,还要执行一个个输入框和点击方法
所以每个业务类能封装就封装,要保证testcase里只有输入数据值
TestCase.py 代码如下
import unittest
from selenium import webdriver
import time
from po.LoginPage import LoginPage
from ddt import ddt,data,unpack
@ddt
class testlogin(unittest.TestCase,LoginPage):
def setUp(self) -> None:
print('每个用例的前置')
self.driver = webdriver.Chrome()
self.driver.get("http://ip:port/")
def tearDown(self) -> None:
print('每个用例的后置')
time.sleep(3)
self.driver.quit()
@data(('zhou','123456'),('admin','123456'))
@unpack
def test_login(self,username,pwd):
# self.driver.find_element(*LoginPage.username).send_keys('zhou')
# self.driver.find_element(*LoginPage.pwd).send_keys('123456')
# self.driver.find_element(*LoginPage.login_button).click()
# time.sleep(3)
#封装用户名输入方法,密码输入方法,点击登陆按钮
# self.username_input('zhou')
# self.pwd_input('123456')
# self.click_button()
#直接调用LoginPage封装的登陆方法
self.login(username,pwd)
time.sleep(1)
url=self.driver.current_url
print(url)
self.assertEqual(url,'http://ip:port/welcome',msg='判断url是否是欢迎页面')
if __name__ == '__main__':
unittest.main()
上面test_login方法下面有两个注释掉的,是假设LoginPage里没有封装login方法而写的,一步步循序渐进,最后封装了login方法的话,在testcase里只需要调用login方法了,简单多了,最后还加了断言。
在用当前url做断言的时候有个坑,就是我明明登陆进去了,但是取得的driver.current_url一直是user/login,花费了半天时间,最后加了个等待时间就好了,真是太坑了,所以说做selenium的UI自动化,在定位元素或者断言的时候万能解决办法是先加个等待时间 time.sleep(1),不行的话再看其他办法
以上,就是PO设计模式的自己的见解,以及例子,记录一下也方便以后查找