PO
模型介绍
在自动化中,
Selenium
自动化测试中有一个名字经常被提及
PageObject(
思想与面向对象的特征相同)
,通常
PO
模型可以大大提高测试用例的维护效率
优点
:
重用,业务和对象分离,代码结构清晰,方便代码维护
PageObject
设计模式
![](https://i-blog.csdnimg.cn/blog_migrate/2922b0f293ad33a797e9cfd9b550ddcf.png)
PO
的核心要素
1.
在
PO
模式中抽离封装集成一个
BasePage
类,该基类应该拥有一个只实现
webdriver
实例的属性
2.
每一个
page
都继承
BasePage
,通过
driver
来管理本
page
中元素,将
page
中的操作封装成一个个方法
3.TestCase
继承
unittest.Testcase
类,并依赖
page
类,从而实现相应的测试步骤
非
PO
实现
效果展示
![](https://i-blog.csdnimg.cn/blog_migrate/695dcf0c98525244d4f302ef34df3781.png)
代码展示
from
selenium
import
webdriver
from
time
import
sleep
driver
=
webdriver
.
Firefox
()
driver
.
get
(
"http://www.baidu.com"
)
driver
.
find_element_by_id
(
"kw"
).
send_keys
(
"jack"
)
sleep
(
1
)
driver
.
find_element_by_id
(
"su"
).
click
()
sleep
(
2
)
driver
.
quit
()
代码分析
不同的运行脚本环境,游览器不同:驱动
webdriver.Firefox()
可以剥离
请求地址的变化
(
生产环境和测试环境
):url = http://www.baidu.com
可以剥离
操作元素时,常常要等待元素加载完成方可进行操作:可以把
webdriver
提供的
find_element*
方法封装,在元素操作前,先判断元素是否可以操作
实际测试场景中,可能有多个测试场景,如果每个测试场景都需要维护
url,
游览器驱动
,
元素定位等
,
效率会非常低
因此基于以上分析,是否可以设计一个所有测试界面(
selenium
本身是
B/S
系统开展测试)的基类,来 维护公共的方法,此处定义名字为BasePage.py,
用于存放页面公共方法及
webdriver
原有方法二次封装等。
PO
实现
实现
BasePage
![](https://i-blog.csdnimg.cn/blog_migrate/48de81d1f1ff0c6f7f15e92ba4fd8be2.png)
代码展示:
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains #鼠标操作 class BasePage(): '''BasePage封装所有界面都公用的方法。例如driver,find_element等''' '''实例化BasePage类时,事先执行的__init__方法,该方法需要传递参数''' def __init__(self,driver,url): self.driver = driver self.base_url = url # 进入网址 def get(self): self.driver.get(self.base_url) #元素定位,替代八大定位 def get_element(self,*locator): return self.driver.find_element(*locator) #点击 def left_click(self,*locator): ActionChains(self.driver).click(self.get_element(*locator)).perform() #输入 def send_text(self,text,*locator): self.driver.find_element(*locator).send_keys(text) #清除 def clear_text(self, *locator): self.driver.find_element(*locator).clear() # 表单切换 def switch_iframe(self,*locator): self.driver.switch_to.frame(self.driver.find_element(*locator)) #窗口切换 def switch_window(self,n): self.driver.switch_to.window(self.driver.window_handles[n])
实现
SearchPage
![](https://i-blog.csdnimg.cn/blog_migrate/fd209925ae0e8afed2bae7e393cc117f.png)
代码展示:
from selenium.webdriver.common.by import By from base_demo.BasePage import BasePage class Search(BasePage): def __init__(self,driver,url): BasePage.__init__(self,driver,url) # 进入百度 def open_baidu(self): self.get() # 输入搜索内容 def input_search_content(self,text): self.send_text(text,By.ID,"kw") # 点击百度一下按钮,搜索 def click_baidu_search(self): self.left_click(By.ID,"su") # 点击输入hao123 def hao123(self): self.left_click(By.XPATH,'//*[@id="1"]/h3/a[1]')
实现
TestCase
![](https://i-blog.csdnimg.cn/blog_migrate/dcd4c650908e0f030955f87770047fe7.png)
代码展示:
import unittest from selenium import webdriver from pagedemo.search_page import Search from pagedemo.ditu import Search2 class BaiBu(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.driver = webdriver.Chrome(executable_path=r'G:\Google\Application\chromedriver.exe') # 10秒之内执行完,如果没执行完则报错 cls.driver.implicitly_wait(10) def test001(self): # 网址 url="http://www.baidu.com" # 第一个方法里面的传值 s = Search(self.driver,url) # 调用第一个方法里面的方法 s.open_baidu() s.input_search_content("123") s.click_baidu_search() s.hao123() # 获取句柄,并调用 self.driver.switch_to.window(self.driver.window_handles[1]) def test002(self): # 因为相当于继续往下执行,调用第一个方法里面的url,所以这个里面可以不填 url="" # 第二个方法里面的传值 s=Search2(self.driver,url) # 调用第二个方法里面的方法 s.baidu() @classmethod def tearDownClass(cls) -> None: # cls.driver.quit() # 设置为pass则表示执行完停留当前页面,如果不设置为pass则执行完最后一条,直接关闭页面 pass if __name__ == '__main__': unittest.main()
第一个页面的方法的实现:
代码展示:
from selenium.webdriver.common.by import By from base_demo.BasePage import BasePage class Search(BasePage): def __init__(self,driver,url): BasePage.__init__(self,driver,url) # 进入百度 def open_baidu(self): self.get() # 输入搜索内容 def input_search_content(self,text): self.send_text(text,By.ID,"kw") # 点击百度一下按钮,搜索 def click_baidu_search(self): self.left_click(By.ID,"su") # 点击输入hao123 def hao123(self): self.left_click(By.XPATH,'//*[@id="1"]/h3/a[1]') 第二个页面的方法的实现:
代码展示:
from selenium.webdriver.common.by import By from base_demo.BasePage import BasePage class Search2(BasePage): def __init__(self,driver,url): BasePage.__init__(self,driver,url) def baidu(self): self.left_click(By.LINK_TEXT,"百度地图")
组织代码:
总结:
PO
设计模式中的
BasePage
基类对应案例中的
BasePage.py
文件
PO
模式中的
pages
中的案例显示
Search.py
PO
模式设计中
TestCase
对应案例中的
TestCase.py
PO
模式的优点
1:PO
提供了一种业务流程与页面元素操作分离的模式,这使得测试代码变得更加清晰
2
:页面对象与用例分离,使得我们更好的复用对象
3
:可复用的页面方法代码会变得更加优化
4
:更加有效的命令方式使得我们更加清晰的知道方法所操作的
UI
元素