UI自动化实战进阶PO设计模式
前言
经过前面的实战我们已经编写了几个测试用例,下面我们要用PO设计模式来调整我们的代码,让页面元素和测试业务进行分离,这样看起来直观而且后期的维护也方便。
python有一个第三方的PO设计的库,既然已经有了轮子,我们就可以直接造车了。
安装
首先我们来安装
pip install page_objects
Code
页面封装
#pages.py
from page_objects import PageElement, PageObject
class Blog_Login_Page(PageObject):
'''登陆页面'''
login_user = PageElement(id_ = 'user_login')
login_passwd = PageElement(id_ = 'user_pass')
login_jizhu = PageElement(id_ = 'rememberme')
login_button = PageElement(id_ = 'wp-submit')
测试用例
#test_case.py
import unittest
from selenium import webdriver
from pages import Blog_Login_Page
username = passwd = 'pyse_24'
url = 'http://139.199.192.100:8000/wp-login.php'
class Test_Blog(unittest.TestCase):
'''博客测试用例前置和后置'''
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.get(url)
self.driver.implicitly_wait(10)
self.driver.maximize_window()
blog_home = Blog_Login_Page(self.driver)
blog_home.login_user.send_keys(username)
blog_home.login_passwd.send_keys(passwd)
blog_home.login_jizhu.click()
blog_home.login_button.click()
def tearDown(self):
self.driver.quit()
class Test_login(Test_Blog):
'''博客登陆测试用例'''
def test_login_success(self):
title_url = self.driver.current_url
assert 'wp-admin' in title_url, '登陆不成功或者断言错误'
if __name__ == '__main__':
unittest.main()

下面我们在把之前的其他的用例按照这个模式进行整合
首先继续进行封装,如果后面的页面越来越多,我们就必须封装多个,并进行分类,首先创建一个pages的文件夹,然后将之前的封装文件改名成blog_login_page.py,然后创建新的封装页面文件
这里增加了目录以及修改文件名称,导包时可能会有点问题了,后面我的代码会有解决办法
#blog_write_page.py
from page_objects import PageElement, PageObject ,MultiPageElement
class Blog_Post_Page(PageObject):
home_post = PageElement(css = '#menu-posts > a >.wp-menu-name')
write_post = PageElement(css = '.page-title-action')
write_post_alert = PageElement(css = 'div.components-modal__header > button > svg')
write_post_title = PageElement(css = '#post-title-0')
write_post_text = PageElement(css = '#post-content-0')
write_post_release = PageElement(css = 'button.components-button.editor-post-publish-panel__toggle.editor-post-publish-button__button.is-primary')
write_post_release_button = PageElement(css = 'div.editor-post-publish-panel__header-publish-button > button')
post_release_status = PageElement(css = 'div.components-panel__body.post-publish-panel__postpublish-header.is-opened')
继续封装删除博客的页面
#blog_delete_page.py
from page_objects import PageElement, PageObject ,MultiPageElement
class Blog_Post_Page(PageObject):
home_post = PageElement(css = '#menu-posts > a >.wp-menu-name')
delect_post_locat = PageElement (css = 'td.author.column-author > a')
delect_post_button = MultiPageElement (css = 'td.title.column-title.has-row-actions.column-primary.page-title > div.row-actions > span.trash > a')
页面封装好了,开始写测试用例了,既然页面有了分类,那么我们的测试用例也应该进行分类
首先登陆用例
#test_login_blog.py
from pages.blog_login_page import Blog_Login_Page
import unittest
from selenium import webdriver
import os
import sys
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
username = passwd = 'pyse_24'
url = 'http://139.199.192.100:8000/wp-login.php'
class Test_Blog(unittest.TestCase):
'''博客测试用例前置和后置'''
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.get(url)
self.driver.implicitly_wait(10)
self.driver.maximize_window()
blog_home = Blog_Login_Page(self.driver)
blog_home.login_user.send_keys(username)
blog_home.login_passwd.send_keys(passwd)
blog_home.login_jizhu.click()
blog_home.login_button.click()
def tearDown(self):
self.driver.quit()
class Test_login(Test_Blog):
'''博客登陆测试用例'''
def test_login_success(self):
title_url = self.driver.current_url
assert 'wp-admin' in title_url, '登陆不成功或者断言错误'
if __name__ == '__main__':
unittest.main()
写文章用例
#test_write_blog.py
import unittest
import uuid
import os,sys
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
from pages.blog_write_page import Blog_Post_Page
from test_login_blog import Test_Blog
uid = str(uuid.uuid1())
suid = ''.join(uid.split('-'))
class Test_write_blog(Test_Blog):
'''写博客测试用例'''
def test_write_blog_success(self):
write_blog = Blog_Post_Page(self.driver)
write_blog.home_post.click()
write_blog.write_post.click()
write_blog.write_post_alert.click()
write_blog.write_post_title.send_keys(suid)
write_blog.write_post_text.send_keys(suid)
write_blog.write_post_release.click()
write_blog.write_post_release_button.click()
blog_status = write_blog.post_release_status
assert '已被发布' in blog_status.text, '文章未发布或断言错误'
if __name__ == '__main__':
unittest.main()
删除文章用例
#test_delete_blog.py
import unittest
from time import sleep
from selenium.webdriver.common.action_chains import ActionChains
import os,sys
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
from pages.blog_delete_page import Blog_Post_Page
from test_login_blog import Test_Blog
class Test_delete_blog(Test_Blog):
'''删除博客测试用例'''
def test_delete_blog_success(self):
delete_blog = Blog_Post_Page(self.driver)
delete_blog.home_post.click()
mouse = delete_blog.delect_post_locat
ActionChains(self.driver).move_to_element(mouse).perform()
blog_title_old = delete_blog.delect_post_button
bt = blog_title_old[0].text
blog_title_old[0].click()
blog_title_new = delete_blog.delect_post_button
bt2 = blog_title_new[0].text
assert bt != bt2, '文章未删除成功'
if __name__ == '__main__':
unittest.main()
这样每个用例都是独立的,当然我这里调用了登陆用例的方法,这么写并不推荐,建议还是将登陆用例独立出来,然后另外封装一个成功登陆方法让其他用例调用,具体方法我就不实现了,也算比较简单了。
既然用例独立了,如果我想一次运行多个用例呢?那么我们需要添加一个测试套件,将需要执行的多个测试用例添加进来,如果用例过多添加比较麻烦怎么办?那就执行整个目录下的用例,其中如果有不需要执行的可以使用skip进行跳过,这样灵活的组合基本能满足所有的场景了。
首先创建main目录,再目录中进行执行方法的分类
#run_test_class.py
import unittest
import os,sys
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
print(path)
print(sys.path)
from test_case.test_login_blog import Test_login
if __name__ == '__main__':
# 根据给定的测试类,获取其中所有以test开头的测试方法,并返回一个测试套件
suite1 = unittest.TestLoader().loadTestsFromTestCase(Test_login)
# 将多个测试类加载到测试套件中
suite = unittest.TestSuite([suite1])
# 设置verbosity = 2,可以打印出更详细的执行信息
unittest.TextTestRunner(verbosity=2).run(suite)
这里我遇到一个问题,导包的时候尝试各种方法一直报错,后面无意中执行发现再其他的目录也存在相同的test_case目录名称并且也添加进了系统环境,所以一直查不到其他test_case目录下有包.
这里主要是命名不规范导致的,希望大家都能规范编码,不然一个小问题可能会排查半天

修改目录名称并且和导包的名称
#run_test_class.py
import unittest
import os,sys
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
print(path)
print(sys.path)
from test_blog_case.test_login_blog import Test_login
if __name__ == '__main__':
# 根据给定的测试类,获取其中所有以test开头的测试方法,并返回一个测试套件
suite1 = unittest.TestLoader().loadTestsFromTestCase(Test_login)
# 将多个测试类加载到测试套件中
suite = unittest.TestSuite([suite1])
# 设置verbosity = 2,可以打印出更详细的执行信息
unittest.TextTestRunner(verbosity=2).run(suite)
执行成功,如果需要执行那几个测试类直接导入再添加到套件里面进行执行即可

下面我们来写执行整个目录的方法
#run_test_discover.py
import os
import unittest
if __name__ == '__main__':
path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'test_blog_case')
suite = unittest.defaultTestLoader.discover(path, pattern='test*.py')
runner = unittest.TextTestRunner()
runner.run(suite)

再结合skip跳过用例的方法,再需要跳过的测试类或者测试方法添加下面的方法
@unittest.skip(reason):强制跳过,不需要判断条件。reason是跳过原因的描述必须填写。
#test_delete_blog.py
import unittest
from time import sleep
from selenium.webdriver.common.action_chains import ActionChains
import os,sys
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
from pages.blog_delete_page import Blog_Post_Page
from test_login_blog import Test_Blog
@unittest.skip('跳过删除博客用例')
class Test_delete_blog(Test_Blog):
'''删除博客测试用例'''
def test_delete_blog_success(self):
delete_blog = Blog_Post_Page(self.driver)
delete_blog.home_post.click()
mouse = delete_blog.delect_post_locat
ActionChains(self.driver).move_to_element(mouse).perform()
blog_title_old = delete_blog.delect_post_button
bt = blog_title_old[0].text
blog_title_old[0].click()
blog_title_new = delete_blog.delect_post_button
bt2 = blog_title_new[0].text
assert bt != bt2, '文章未删除成功'
if __name__ == '__main__':
unittest.main()
第一个执行的是删除博客用例并出现了s跳过的标记,为什么先执行删除博客这里需要了解unittest的执行顺序,具体知识不在此文章范围内,需要了解的自行百度。

UI自动化实战进阶PO设计模式的更多相关文章
- UI自动化实战进阶后续
前言 最近几天因为回老家的缘故,暂时没空学习和记录,好不容易抽空那就赶紧开始后面的实战. 前面我们已经基本完成了测试的框架,并且也有了PO设计模式,后面我们还缺少什么呢?做为自动化测试最主要的测试报告 ...
- 说说UI自动化中的PO模式
PO模式,全称PageObject模式,即页面对象模式.将页面定位与业务操作分离. po模式有以下几个优点: 1.易读性好 2.扩展性高 3.复用性强 4.维护性好 5.代码冗余率低 了解了po模式及 ...
- UI自动化学习笔记- PO模型介绍和使用
一.PO模型 1.PO介绍:page(页面) object(对象) 在自动化中,Selenium 自动化测试中有一个名字经常被提及 PageObject (思想与面向对象的特征相同),通常PO 模型可 ...
- python UI自动化实战记录十一: 总结
首先说说为什么想起来用自动化脚本来实现该项目的自动化. 工作还是以手工测试为主,业务驱动型的项目大概就是这样,业务不停地变,不断的迭代. 自动化测试实施的先决条件: 一 得有时间. 如果有时间大部分的 ...
- python UI自动化实战记录五:测试页面2 pageobject
该部分记录测试页面2-StrategyPage,所有页面2上的元素定位.操作.获取属性等方法都写在该类中. 1 页面2继承自BasePage: 2 页面2第一部分写的是所有的定位器 3 页面2第二部分 ...
- python UI自动化实战记录三:pageobject-基类
脚本思路: 使用pageobject模式,写一个basepage基类,所有页面的通用方法封装到基类中.比如打开页面,关闭页面,等待时间,鼠标移到元素上,获取单个元素,获取一组元素,获取元素的子元素,截 ...
- python UI自动化实战记录二:请求接口数据并提取数据
该部分记录如何获取预期结果-接口响应数据,分成两步: 1 获取数据源接口数据 2 提取后续页面对比中要用到的数据 并且为了便于后续调用,将接口相关的都封装到ProjectApi类中. 新建python ...
- python UI自动化实战记录一:测试需求与测试思路
测试需求: 项目包含两个数据展示页面,数据均来自于四个数据源接口. 测试操作步骤: 选择5个大类型中的一个,每个大类型下有3个子类型,选择任一子类型,页面数据更新.需验证页面上的数据与数据源接口数据一 ...
- python UI自动化实战记录十:执行测试及测试报告
使用简单的unittest.TextTestRunner. 思路: 1 在report目录下创建当日测试报告目录 20190113 2 创建测试报告文件 f = 时间戳.txt 3 加载测试集,运行测 ...
随机推荐
- hbase读写优化
一.hbase读优化 客户端优化 1.scan缓存是否设置合理? 优化原理:一次scan请求,实际并不会一次就将所有数据加载到本地,而是多次RPC请求进行加载.默认100条数据大小. 优化建议:大sc ...
- openstack octavia的实现与分析(一)openstack负载均衡的现状与发展以及lvs,Nginx,Haproxy三种负载均衡机制的基本架构和对比
[负载均衡] 大量用户发起请求的情况下,服务器负载过高,导致部分请求无法被响应或者及时响应. 负载均衡根据一定的算法将请求分发到不同的后端,保证所有的请求都可以被正常的下发并返回. [主流实现-LVS ...
- TCP连接的建立与释放(超详细)
前言:在计算机网络协议中,TCP只是其中一个,然而在网络使用中,TCP也是最离不开的协议之一,它的重要性毋庸置疑,最最重要的是,面试的重点就是它啊,呜呜~~,今天我们一起来看下TCP的连接建立与释放, ...
- LeetCode844 比较含退格的字符串
题目描述: 给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果. # 代表退格字符. 示例 1: 输入:S = "ab#c", T = ...
- Java进阶专题(二十一) 消息中间件架构体系(3)-- Kafka研究
前言 Kafka 是一款分布式消息发布和订阅系统,具有高性能.高吞吐量的特点而被广泛应用与大数据传输场景.它是由 LinkedIn 公司开发,使用 Scala 语言编写,之后成为 Apache 基金会 ...
- linux网络工具nc命令
nc是netcat的简写,有着网络界的瑞士军刀美誉.因为它短小精悍.功能实用,被设计为一个简单.可靠的网络工具. nc命令的作用 (1)实现任意TCP/UDP端口的侦听,nc可以作为server以TC ...
- 【Linux】使用 iperf 测试 Linux 服务器带宽
iperf 简介 iperf 是一个用于测试网络带宽的命令行工具,可以测试服务器的网络吞吐量.目前发现两个很实用的功能: 测试服务器网络吞吐量:如果我们需要知道某台服务器的「最大」网络带宽,那么最好在 ...
- 【Linux】linux rinetd 端口转发部署
linux下简单好用的工具rinetd,实现端口映射/转发/重定向 Rinetd是为在一个Unix和Linux操作系统中为重定向传输控制协议(TCP)连接的一个工具.Rinetd是单一过程的服务器,它 ...
- vxfs(Veritas File System)扩充目录大小
1.新增加一个磁盘并初始化 # vxdisk list # vxdisksetup -i 3pardata0_22 2.将新增加的磁盘合并到磁盘组中 # vxdg -g testdg01 adddis ...
- SAP中数据库表长度的界定
SAP中,如何查看表和关键字的长度?通过SE11菜单栏Extras->table width 可以看到.然而SAP在系统也会将表分类,特别是在可扩展的表维护视图中,分为如下几类 ult ...