多测师肖sir_高级金牌讲师_ui自动化po框架版本01

ui自动化po框架
一、po框架
1、基本介绍
(1)po模式是page object model的缩写(简称:po或pom)
(2) po模式的核心思想:分层,实现耦合 实现:业务流程与页面元素操作分离的模式。
(3)作用:
a、提高测试用例的可维护性、可读性
b、降低代码的耦合性
c、实现脚本重复使用

二、自动化测试框架分层如下:

结构图:
在这里插入图片描述
框架的思想:把整个用例进行拆分6个包
‘’'1、先创建一个dcscms项目
在创建一个conf包存放所有配置文件信息(比如项目路径和数据,用例的路径)
在创建一个包
放数据(测试数据)
在Data包中可以存放xlsx文件数据(放测试数据)
测试环境的一些url地址和账号密码可以放在TestDta中
在创建一个report包==存放测试报告
在创建一个public公共公开的包(存放一些功能用例)
在public包中创建pages存放元素层流程层(封装所有页面的公共方法,基类)
在public包中创建utils包(处理公共类公共函数都存放在此)
可以在utils中来读取pages中封装的登录的流程(封装读取ini文件或者EXCEL表格的工具类和工具函数
在创建一个TestCase用例包用来存放用例(编写测试用例)
在创建一个run_all用来运行
通过运行测试用例中封装好的用例在运行然后在repot中生成测试报告

================================

实战:
一、新建项目
在这里插入图片描述
二、在新建6个包

详解
1、在conf包中先把项目的路径和每个包的路径写好,
作用:方便我们后面引用
定义cms_path的py文件:

"""
此模块用来定义项目及其下面的包的路径
"""
import os  #导入os模块
#定义项目路径
base_path = os.path.dirname(os.path.dirname(__file__))    # 项目所在的路径
# print(base_path)
# data路径
data_path = os.path.join(base_path,'data')
# pages路径
pages_path = os.path.join(base_path,'public','pages')
# utils路径
utils_path = os.path.join(base_path,'public','utils')
# report路径
report_path = os.path.join(base_path,'report')
# run路径
run_path = os.path.join(base_path,'run')
# testcase路径
testcase_path = os.path.join(base_path,'testcase')

在创建一个ini文件命名:conf.ini 这里都是写配置文件, 存放我们测试数据url,账号,密码,url等

[test_data]  #节点#section     #option
url = http://cms.duoceshi.cn/cms/manage/login.do
username = admin
password = 123456
[exception_data_1]
username = admin
password = 654321
[exception_data_2]
username = admin111
password = 654321
[mysql_data]
host_name = 192.168.1.1
port = 3306
username = 1233333
[useradd_data]
username = dcs
password = 123456
phoneno = 13566667777
useremail = 12345@qq.com
useraccount = admin8765
userpwd = 123456

===============================================
在data中也可以用excel表格写数据(和ini一样都可以存放数据)
文件名:cmsdata.xlsx
编写url和username和passwor
在这里插入图片描述

在工具类中封装读取ini文件 read_conf文件

from configparser import ConfigParser
from conf.cms_path import *
import os
class R_conf(ConfigParser):'''当前这个类是用来处理conf.ini文件的工具类'''def __init__(self,filename):super(R_conf,self).__init__()  #继承父类的构造方法self.filename = filename  #把传进来的形式参数赋值给到实例变量self.filenameself.read(self.filename)  #打开ini文件进行读取def get_value(self,section,option):'''获取ini文件中的section下面对应的option的value值'''value = self.get(section,option)return value
path = os.path.join(conf_path,'conf.ini')
conf =R_conf(path)
print(conf.get_value('test_data','url'))

在封装一个读取excel表格类

import openpyxl   #操作Excel表格的库
from conf.cms_path import *
import osclass R_Excel(object):'''封装一个班读取Excel表格的工具类'''def __init__(self,filename,sheet_name):self.filename = filenameself.sheet_name = sheet_namedef open(self):'''封装一个打开Excel表格的工具方法'''#通过openpyxl模块调用load_workbook函数打开filename文件self.wb = openpyxl.load_workbook(self.filename)# 通过self.wb这个Excel文件的对象读取对应的sheet页面的self.sh = self.wb[self.sheet_name]def read_data(self,row,col):self.open()cell = self.sh.cell(row=row, column=col)return cell.value# if __name__ == '__main__':
#     path = os.path.join(data_path, 'testdata.xlsx')
#     read_excel = R_Excel(path, 'cms_data')
#     print(read_excel.read_data(1,1))

以上都是数据的准备,和我们讲的接口自动化前面差不多。

====================================
接下来我们开始封装基类:在public中的page下新建一个basepage的py文件,
比如: 所有用例要用到的元素定位,以及输入框输入,点击,下拉等公共方法
我们所有的用例都要继承它:(,跑完,关闭,我们换一个思路,让所有的用例都在在同一个对象里面跑)
注解:
首先我们创建一个类,BasePage(object):
BasePage 类是一个基础页面类,它使用单例设计模式来确保在整个应用中只创建一个 WebDriver 对象。WebDriver 通常用于自动化浏览器交互,例如打开网页、填写表单、点击按钮等。

_driver 是一个类变量,用于存储 WebDriver 对象。由于它在类级别定义,所以所有实例都可以访问和共享这个变量。
get_driver 是一个类方法(用 @classmethod 装饰器表示)。它用于获取 _driver 变量。
如果 _driver 为空(即还没有创建 WebDriver 对象),则创建一个新的 WebDriver 对象并将其赋值给 _driver。
如果 _driver 不为空,则直接返回它。
这种设计使得在整个应用中,不论你创建多少个 BasePage 的实例,你都会得到同一个 _driver 对象。这对于在多线程环境下进行自动化测试或网页交互非常有用,因为它确保了所有线程都使用同一个 WebDriver 实例;
driver = None是一种常见的写法,用于声明一个变量并初始化为None。这种写法表明driver变量在初始状态下没有赋值。
这个写法通常用于以下情况:

初始化变量:当你需要声明一个变量,但不确定它的初始值时,可以将它初始化为None。这表示该变量当前没有有效的值。
判断变量是否被赋值:通过检查变量是否为None,可以判断该变量是否已经被赋值。如果变量为None,则说明它还没有被赋值。
占位符:在编写代码时,有时候需要声明一个变量,但暂时不需要使用它。为了不影响代码的执行,可以将它初始化为None,作为占位符使用。

所以我们创建类方法: @classmethod (为什么我们创建类方法,因为类方法可以直接被类调用)

class BasePage(object):_driver = None  #声明一个变量并初始化为None@classmethoddef get_driver(cls): #通过get_driver获取driver对象#单例设计模式:是为了保证每个用例用的都是同一个浏览器对象#(比如:篮球场上进行100次进行投篮练习,100个篮球练习;用同一个篮球,进行100次投篮,这就是单例模式)if not cls._driver:cls._driver = webdriver.Chrome()   #return cls._driver
#以上是一个单例模式
#除了打开浏览器以外,我们还要进行元素定位,我们也封装一个类方法,名字是find_elemnet
#比如 baidu=(id,‘kw’)@classmethod    #def find_element(cls,element):#定位元素,我们用了很多种元素定位方法,"""对selenium的元素定位方法进行二次封装,到时候进行元素定位的时候,只需要调用同一个方法就行了,参数不一样:param element: 元素属性"""type_name = element[0]value_name = element[1]  if type_name == 'id': #可以写一个if多分支方法ele = cls._driver.find_element_by_id(value_name)elif type_name == 'name':ele = cls._driver.find_element_by_name(value_name)elif type_name == 'class':ele = cls._driver.find_element_by_class_name(value_name)elif type_name == 'xpath':ele = cls._driver.find_element_by_xpath(value_name)elif type_name == "tag_name":ele = cls._driver.find_element_by_tag_name(value_name)elif type_name == 'link_text':ele = cls._driver.find_element_by_link_text(value_name)elif type_name == 'partial_link_text':ele = cls._driver.find_element_by_partial_link_text(value_name)elif type_name == 'css':ele = cls._driver.find_element_by_css_selector(value_name)else:raise ValueError("请输入正确的属性参数") #如果不是输入定位方法不对,手动触犯异常,请输入正确的参数return ele  #把网页元素返回去这里我们封装一个定位元素工具方法,方便,只要你传元素方法和元素属性值@classmethoddef click(cls,ele):return ele.click()@classmethoddef sendKeys(cls,ele,text):"""封装输入内容的方法:param ele:  元素对象:param text:  文本信息:return:"""return ele.send_keys(text)@classmethoddef sleep(cls,sec):"""封装一个线程等待方法:param sec: 等待的时间,单位为秒:return:"""return sleep(sec)@classmethoddef wait(cls,sec):"""封装一个隐式等待:param sec::return:"""return cls._driver.implicitly_wait(sec)@classmethoddef get_text(cls,ele):"""封装一个获取元素的文本信息的方法:param ele::return:"""return ele.text@classmethoddef get_attribute(cls,ele,typename):return ele.get_attribute(typename)@classmethoddef maximize_window(cls):return cls._driver.maximize_window()@classmethoddef switch_frame(cls,ele):return cls._driver.switch_to.frame(ele)if __name__ == '__main__':driver = BasePage.get_driver()driver.get('http://cms.duoceshi.cn/cms/manage/login.do')sleep(2)ele = BasePage.find_element(('id','userAccount'))ele.send_keys('admin')

接下来我们写用例:
写下登录和用户中心的用例

"""
此模块用来编写登录的测试用例
"""from config.config import *
from public.pages.base_page import BasePage
from public.pages.pages_element import Pages_Element as p
from public.utils.handle_excel import Read_Excel
from public.utils.handle_ini import Read_Ini
import unittest
import os#获取访问页面的url地址
ini_file = os.path.join(data_path,'data.ini')
read = Read_Ini(ini_file)
url = read.read_ini('test_data','url')
username = read.read_ini('test_data','username')
passwd = read.read_ini('test_data','password')ex_username = read.read_ini('exception_data_1','username')
ex_passwd = read.read_ini('exception_data_1','password')class Test_Login(unittest.TestCase):@classmethoddef setUpClass(cls):cls.driver = BasePage.get_driver()@classmethoddef tearDownClass(cls):BasePage.sleep(3)del cls.driverdef setUp(self):self.driver.get(url)self.driver.maximize_window()BasePage.sleep(3)def test_1_login(self):ele = BasePage.find_element(p.userName)BasePage.sendKeys(ele,username)BasePage.wait(5)ele2 = BasePage.find_element(p.passWord)BasePage.sendKeys(ele2,passwd)BasePage.wait(5)ele3 = BasePage.find_element(p.loginBtn)BasePage.click(ele3)ele4 = BasePage.find_element(p.exitBtn)value = BasePage.get_attribute(ele4,'title')self.assertEqual(value,'退出')BasePage.sleep(2)def test_2_login(self):ele = BasePage.find_element(p.userName)BasePage.sendKeys(ele,ex_username)BasePage.wait(5)ele2 = BasePage.find_element(p.passWord)BasePage.sendKeys(ele2,ex_passwd)BasePage.wait(5)ele3 = BasePage.find_element(p.loginBtn)BasePage.click(ele3)BasePage.sleep(2)def test_3_login(self):passif __name__ == '__main__':unittest.main()

添加用户

#coding:utf-8from config.config import *
from public.pages.base_page import BasePage
from public.pages.pages_element import Pages_Element as p
from public.utils.handle_excel import Read_Excel
from public.utils.handle_ini import Read_Ini
from public.utils.login import Cms_Login as cm
import unittest
import osini_path = os.path.join(data_path,'data.ini')
read = Read_Ini(ini_path)usrname = read.read_ini('useradd_data','username')
pwd = read.read_ini('useradd_data','password')
phoneno = read.read_ini('useradd_data','phoneno')
useremail = read.read_ini('useradd_data','useremail')
useraccount = read.read_ini('useradd_data','useraccount')
userpwd = read.read_ini('useradd_data','userpwd')class Test_Adduser(unittest.TestCase):@classmethoddef setUpClass(cls):cls.driver = cm().suc_login()@classmethoddef tearDownClass(cls):del cls.driverdef play(self):passdef test_1_adduser(self):ele1 = BasePage.find_element(p.menuUser)BasePage.click(ele1)BasePage.sleep(1)ele2 = BasePage.find_element(p.userMana)BasePage.click(ele2)BasePage.sleep(1)ele3 = BasePage.find_element(p.iframe1)BasePage.switch_frame(ele3)BasePage.wait(3)ele4 = BasePage.find_element(p.addUserBtn)BasePage.click(ele4)BasePage.wait(3)ele5 = BasePage.find_element(p.iframe2)BasePage.switch_frame(ele5)BasePage.wait(3)ele6 = BasePage.find_element(p.customerName)BasePage.sendKeys(ele6,usrname)if __name__ == '__main__':unittest.main()

==========================================
我们针对定位元素也可以封装:
建py文件一个命名:pages_elemnet,我们可以把所有的元素定位放在这个文件中,
按照定位流程书写:
我们把页面元素定位进行抽离的四项被称为:po模式

"""
此模块用来保存各个页面的网页元素的属性信息
"""class Pages_Element():"""此类用来存放网页元素的属性信息"""# 1、用户名输入框的属性userName = ('id','userAccount')# 2、密码输入框的属性passWord = ('id','loginPwd')# 3、登录按钮的属性loginBtn = ('id','loginBtn')# 4、登录页取消按钮的属性cancelBtn = ('xpath','//*[@id="userloginform"]/div[4]/input[2]')# 5、退出按钮的属性exitBtn = ('xpath','/html/body/header/span[2]/a')# 6、个人中心按钮的属性menuUser = ('xpath','//*[@id="menu-user"]/dt')# 7、用户管理选项的属性userMana = ('link_text','用户管理')# 8、第一层iframe框的属性iframe1 = ('name','/cms/manage/user-list.html')# 9、添加用户按钮的属性addUserBtn = ('partial_link_text','添加用户')# 10、第二层iframe框的属性iframe2 = ('name','xubox_iframe1')# 11、用户姓名输入框属性 ----- 添加用户操作customerName = ('name','userName')# 12、手机号输入框属性  ----- 添加用户操作phoneNumber = ('id','user-tel')# 13、登录用户输入框属性  ---- 添加用户操作userAccount = ('id','userAccount')# 14、登录用户密码输入框属性 ---- 添加用户操作loginPwd = ('id','loginPwd')# 15、二次确认密码输入框属性  ------- 添加用户操作confirmPwd = ('id','confirmPwd')# 16、邮箱输入框属性   ------- 添加用户操作userEmail = ('id','user-email')# 17、提交按钮属性  ----------  添加用户操作submitBtn = ('id','submitBtn')

==========================
假如我要写第二条用例的时候

==========================
然后再运行用例

#coding:utf-8import sys
sys.path.append('.')    #添加当前所在的目录到环境变量中
sys.path.append('..')   #添加上级目录到环境变量中import unittest
from public.utils.HTMLTestRunnerNew import HTMLTestRunner
import os
from config.config import *
def run_all(report_file,sd,pt,tester):f = open(report_file,'wb')suite1 = unittest.defaultTestLoader.discover(start_dir=sd,pattern=pt)runner = HTMLTestRunner(stream=f,title='ui自动化测试报告',description='运行结果如下',tester=tester)runner.run(suite1)
if __name__ == '__main__':report_file = os.path.join(report_path,'report_ui.html')run_all(report_file,testcase_path,'test*.py','dcs')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/137389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何从存档服务器上完全删除PDM用户

当创建新用户时使用“PDM 登录”类型(如下图),PDM用户名和密码会存储于存档服务器的注册表中。 存档服务器的注册表位置如下: HKEY_LOCAL_MACHINE\SOFTWARE\SolidWorks\Applications\PDMWorks Enterprise\ArchiveServer\ConisioU…

HTML的初步学习

HTML HTML 描述网页的骨架, 标签化的语言. HTML 的执行是浏览器的工作,浏览器会解析 html 的内容,根据里面的代码,往页面上放东西,浏览器的工作归根结底,还是以汇编的形式在CPU上执行. 浏览器对于html语法格式的检查没有很严格,即使你写的代码有一些不合规范之处,浏览器也会尽可…

分享Python的十大库,这你一定得知道!

文章目录 前言关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 前言 Python为我们提供了非常完善的基础库&#…

c: struct sort descending and ascending in windows and Ubuntu

/*** file StudentStructSort.h* author geovindu,Geovin Du,涂聚文 (geovindu163.com)* ide: vscode c11,c17 Ubuntu 22.4* brief 结构体排序示例* date 2023-11-05* version 0.1* copyright geovindu 站在巨人的肩膀上 Standing on the Shoulders of Giants**/#ifnd…

计算机技术专业CSIT883系统分析与项目管理介绍

文章目录 前言一、学科学习成果二、使用步骤三、最低出勤要求四、讲座时间表五、项目管理 前言 本课程介绍了信息系统开发中的技术和技术,以及与管理信息技术项目的任务相关的方法和过程。 它研究了系统分析师、客户和用户在系统开发生命周期中的互补角色。 它涵盖…

Python+reuqests自动化接口测试

1.最近自己在摸索Pythonreuqests自动化接口测试,要实现某个功能,首先自己得有清晰的逻辑思路!这样效率才会很快! 思路--1.通过python读取Excel中的接口用例,2.通过python的函数调用,get/Post 进行测试&…

Apple :苹果将在明年年底推出自己的 AI,预计将随 iOS 18 一起推出

本心、输入输出、结果 文章目录 Apple :苹果将在明年年底推出自己的 AI,预计将随 iOS 18 一起推出前言三星声称库克相关图片弘扬爱国精神 Apple :苹果将在明年年底推出自己的 AI,预计将随 iOS 18 一起推出 编辑:简简单…

python操作链接数据库和Mysql中的事务在python的处理

python操作数据库 pymysql模块: pip install pymysql作用:可以实现使用python程序链接mysql数据库,且可以直接在python中执行sql语句 添加操作 import pymysql #1.创建链接对象c conn pymysql.Connect(host127.0.0.1,#数据库服务器主机地址port3306, #mysql的端口…

通过postgis空间库导入sql格式的矢量数据到arcgis中

1、在postgis中创建数据库 命名为test3 2、创建空间扩展 3、导入sql矢量文件 进入psql.exe目录中 进入dos命令框中 输入命令,其中host输入自己的主机ip,database为自己的数据库名称,数据路径修改为自己电脑上的路径,注意反斜杠 psql

Node.js |(七)express案例实践:记账本 | 尚硅谷2023版Node.js零基础视频教程

文章目录 📚基本结构搭建📚响应静态网页📚获取表单数据📚借助lowdb保存账单信息📚完善成功提醒📚账单列表📚删除账单📚final 学习视频:尚硅谷2023版Node.js零基础视频教程…

MySQL–第4关:查询用户日活数及支付金额

MySQL–第4关:查询用户日活数及支付金额 – WhiteNights Site 标签:MySQL 非常好的题,爱来自中国。 题目 没啥用 任务描述 现有3张业务表,详见如下: 需要输出结果如下,没有支付的日期不需要显示,请写出对…

前端缓存机制——强缓存、弱缓存、启发式缓存

强缓存和弱缓存的主要区别是主要区别在于缓存头携带的信息不同。 强缓存: 浏览器发起请求,查询浏览器的本地缓存,如果找到资源,则直接在浏览器中使用该资源。若是未找到,或者资源已过期,则浏览器缓存返回未…

Python最基础的五个部分代码,零基础也能轻松看懂。

文章目录 前言一、表达式二、赋值语句三、引用四、分支语句五、循环语句关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼…

K8S知识点(七)

(1)实战入门-Namespace kubernets:系统创建的资源在这个命名空间里 ,集群组件资源 kubrnets组件也是以pod的形式运行的 命令行方式操作 查看namespace和详情: 创建和查看和删除: 使用过配置文件操作&am…

leetcode做题笔记226. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2: 输入:root [2,1,3] 输出:[2,3,1]示例 3&#x…

查找或替换excel换行符ctrl+j和word中的换行符^p,^l

一、excel中 直接上图。使用ctrlh调出替换,查找内容里按ctrlj(会出现一个闪的小点),即为换行符。 二、word中 在word中,^p和^l分别代表换行符(enter)和手动换行符(使用shiftenter&…

Python使用Numba装饰器进行加速

Python使用Numba装饰器进行加速 前言前提条件相关介绍实验环境Numba装饰器进行加速未加速的代码输出结果 numba.jit加速的代码输出结果 前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可点击进入Python日常小操作专栏、Ope…

效率提升75%!要做矩阵号,更要做好矩阵号管理

在如今的信息数字化时代,面对竞争日趋激烈的市场,数字化转型成为了企业提高效率和竞争力、实现可持续发展的重要手段。 这一两年来,我们也发现,越来越多的品牌企业开始探索数字化转型的实践,通过使用自建或者采买的数据…

node插件MongoDB(四)—— 库mongoose 的个性话读取(字段筛选、数据排序、数据截取)(四)

文章目录 一、字段筛选二、数据排序三、数据截取1. skip 跳过2. limit 限定![在这里插入图片描述](https://img-blog.csdnimg.cn/c7067b1984ee4c6686f8bbe07cae9176.png) 一、字段筛选 字段筛选:只读取指定的数据,比如集合(表)中有…

uniapp:打包ios配置隐私协议框

使用uniapp打包ios 上架商店需要配置隐私协议政策弹窗。当用户点击确定后才能继续操作。 首先manifest.json中配置使用原生隐私政策提示框是不支持ios的。不用勾选。 解决思路: 1、新建页面:iosLogin.vue,pages.json中 这个页面需要放在第一…