动化测试框架概念:
自动化测试框架是一个集成体系,这个体系中包含测试功能的函数、测试数据源、测试对以及重要的模块。
作用:用于解决或处理复杂的问题。
对于测试人员来说:
线性脚本的自动化脚本在维护性和可用性上较差,所以利用设计框架来实现自动化测试
框架设计的目标:
设计出来的框架是直接给测试人员或其他测试人员简单向里面不断补充用例,所以我们的框架设计必须
三简化:操作简单、维护简单、拓展简单
设计框架的同时要结合业务流程,不仅靠技术实现,还要对业务流程的理解和把握(重点和难点)
设计框架时要将基础的feng封装成公用的如:断言,定位方法,等
设计用例要与代码分开,便于用例管理,可以采用数据驱动框架实现。比如(ddt数据驱动)
==================================================================
po框架
(1)po(page object 缩写)
(2)业务流程与页面元素操作分离 ,可以简单理解为每个页面下都有一个配置class,配置类就是用来维护页面元素或操作方法
(3)提高测试用例的可维护性、可读性
======================================
po 自动化测试框架分层如下:
例如:
==================================================================
总:创建一个项目名(如cms_ui)
**第一个config包:**
在创建一个cofing包==存放所有配置文件信息(比如项目路径和数据,用例的路径)
可以封装路径
在cofing包下面,我们在建一个config .py的配置文件,也可以说全局配置(gloadconfig)
上面这个包:配置所有的包的绝对路径,
第一个,我们要拿到当前项目的路径:
(1) 获取项目包的所在路径
project_path=os.path.dirname(os.path.dirname(__file__)) 固定写法,前面我们讲os的时候有讲过
我们得到了项目路径,我们怎么拿到data包,repeport包 的路径,我们要或取可以使用join 拼接路径
#先定义下config的路径
Config_path=os.path.join(project_path,'Config') print(Config_path)#结果:D:/pycharm/UI_AUTO_PO\Config 在打印下下路径,是不是可以了 图片案例
源码:
# 此模块用来放项目中所有python package的绝对路径 import os # 获取项目包的所在路径 project_path=os.path.dirname(os.path.dirname(__file__)) #项目包中的python package的路径有: Config_path=os.path.join(project_path,'Config') print(Config_path) Data_path=os.path.join(project_path,'Data') #Data包路径 print(Data_path) Data_file=os.path.join(Data_path,'data.ini') #Data包中的文件名 print(Data_file) public_path=os.path.join(project_path,'Public') print(public_path) Pages_path=os.path.join(project_path,'Public','Pages') print(Pages_path) Utils_path=os.path.join(project_path,'Public','Utils') print(Utils_path) Report_path=os.path.join(project_path,'Report') print(Report_path) Run_path=os.path.join(project_path,'Run') print(Run_path) Testcase_path=os.path.join(project_path,'Testcase') print(Testcase_path) =======================================================
**第二个包:data包**
在创建一个data包==放数据(测试数据) 测试环境的一些url地址和账号密码可以放在data中
在data数据包中:放ini文件存放数据,xlsx表格拿数据,yalm文件拿数据
存放数据方法:方法一:ini文件
在data包中创建一data.ini(放测试数据)
读取ini文件要用到一个模块configparser,放在untils的工具类中
比如:ini文件中存放数据,测试环境,测试账号,测试数据等;
我们比如:sit 环境 :根据我们cms来讲解 :比如:url ,usr , pwd等
读取ini文件工具类:
方法二:
在data数据中也可以用.xlsx,在做接口的时候用到xlsx读取数据
方法:
1、创建xlsx文件,
2、在表格中输入url,账号,密码
3、读取xlsx表格
import xlrd import os from UI_AUTO_PO.Config.config import Data_path #导入data数据的绝对路径 #data_path的结果为:D:\pycharm\UI_AUTO_PO\Data class ReadExcel: def __init__(self,filename,sheetname): ''' 封装了读取Excel文档的工具类 ''' datapath = os.path.join(Data_path,filename) #已经拿到了要读取的Excel文件绝对路径的文件名 self.workbook = xlrd.open_workbook(datapath) #读取Excel文档、并且生成一个对象 self.sheetName = self.workbook.sheet_by_name(sheetname) def read_excel(self,rownum,colnum): ''' 封装了读取Excel文档具体行和列的工具方法 ''' value = self.sheetName.cell(rownum,colnum).value return value r=ReadExcel("d.xlsx",'hz') print(r.read_excel(1,0)) print(r.read_excel(1,1)) print(r.read_excel(1,2))
==================================================================
**第三个包:public包** (公共公开的意思)
**#public包下: pages包和utils包**
在创建一个public公共公开的包(存放一些功能用例)
在public包中创建pages存放元素层流程层(封装所有页面的公共方法,基类在BasePage)
===============================================
我写ui自动化用例的线性脚本,我们的步骤要,先创建driver 对象,取打开,定位,获取文本,断言等这些操作
public就是公共公开的,我们在公共公开的类中创建一个basepage,
作用:把所有页面公共公开的方法都封装在BasePage这个基类当中
# 此模块用来封装公共方法,二次封装。比如元素定位、控件操作、线程等待、窗口最大化、选择框或者指定的内容 from selenium import webdriver #导入selenium class Basepage(object): #创建basepae方法 # 1.封装驱动 def driver(self,qd): self.qd=qd # 2.封装打开网址 def url(self,url): self.qd.get(url) # 3.封装窗口最大化 def win(self): self.qd.maximize_window() # 4.封装元素定位方法 def find_elem(self,elems): #设置elems作为一个形参,里面有两个元素,page object设计模式 type=elems[0] #定位方法 value=elems[1] #定位元素 if type=='id': #id定位法 self.elem=self.qd.find_element_by_id(value) elif type=='name': #name定位法 self.elem=self.qd.find_element_by_name(value) elif type=='class': #class定位法 self.elem=self.qd.find_element_by_class_name(value) elif type=='link': #link_text定位法 self.elem=self.qd.find_element_by_link_text(value) elif type=='plink': #partial_link_text定位法 self.elem=self.qd.find_element_by_partial_link_text(value) elif type=='xpath': #xpath定位法 self.elem=self.qd.find_element_by_xpath(value) elif type=='css': #css定位法 self.elem=self.qd.find_element_by_css_selector(value) else: raise ValueError('请输入正确的定位方式') #raise 手动抛异常,手动触发异常 return self.elem # 5.封装send_keys方法 def skeys(self,values): # values 也可以时text self.elem.send_keys(values) # 6.封装click方法 def click(self): self.elem.click() # 7.封装获取文本内容text方法 def text(self): return self.elem.text # 8.封装选择iframe框方法 def frame(self): self.qd.switch_to.frame(self.elem) # 9.封装退出iframe框方法 def unframe(self): self.qd.switch_to.default_content() # 10.封装隐式等待方法 def wait(self,m): self.qd.implicitly_wait(m) # 以下是调试内容 if __name__=='__main__': p=Basepage() p.driver(webdriver.Chrome()) p.url('https://www.baidu.com') p.win() p.wait(3) p.find_elem(('id','kw')) #传入什么元素,就返回什么方法 p.skeys('aaaaa') p.wait(2) p.find_elem(('id','su')) p.click()
-------------------------------------------------------------------------------------------
在public包中创建utils包(处理公共类公共函数都存放在这个包中)
可以在utils中来读取pages中封装的登录的流程(封装读取ini文件或者EXCEL表格的工具类和工具函数
urils中工具类:
(1)读取ini 文件的工具类readconfig .py文件
一般配置文件有哪些格式: ini、xls、xlsx、cnf、conf、csv、yaml
此模块用来读取ini的格式文件
代码:
第一步导入 configparser类(config趴色)
from configparser import ConfigParser #导入configparser模块中的ConfigParser类 from UI_AUTO_PO.Config.config import * #导入配置文件中的所有路径 class Readini(ConfigParser): #定义一个类,继承configparser def __init__(self,filename): #构造一个初始化函数 ConfigParser.__init__(self) #继承ConfigParser类的构造方法 self.read(filename) #创建read的实例方法,读取一个文件,取名filename # section代表ini文件中的中括号内容 -- [section内容] # option代表ini文件中等号前的内容 -- option内容 def read_ini(self,section=None,option=None): #读取ini文件中后缀结尾的文件内容 #定义一个变量value=通过get取获取[section内容]option内容
value=self.get(section,option) #使用继承父类后的get方法进行调用 return value # if __name__ == '__main__': nr = Readini(Data_file) #要读取data的文件就要,获取data中ini文件的路径,先获取data_file url= nr.read_ini('sit', 'sit_url') # 获取data.ini文件的url print(url) user = nr.read_ini('sit', 'sit_zh') # 获取data.ini文件的账号 print(user) pwd = nr.read_ini('sit', 'sit_mm') # 获取data.ini文件的密码 print(pwd)
(2)读取excel 表格
使用xlrd模块
(3)报告模板
(4)邮件模板
=====================================================
**第四个包:report 包**
在创建一个report包==存放测试报告
在report包中创建一个Testrepot目录(存放报告)
主要在run中执行指定路径
======================================================
**第五个包:run包**
在创建一个run包用来运行
通过运行测试用例中封装好的用例在运行然后在report中生成测试报告
# 此模块用来运行测试用例和写测试报告、还有写邮件和发送报告邮件 from UI_AUTO_PO.Config.config import * from UI_AUTO_PO.Public.Utils.mail import * #邮件模块 from UI_AUTO_PO.Public.Utils.HTMLTestRunner import * #报告模块 import time,unittest time=str(time.strftime('%Y-%m-%d_%H-%M-%S')) #注意时间格式的符号 file=Report_path+'\\'+time+'UI自动化报告.html' #报告名称 def auto_run(): f=open(file,'wb') #打开文件 'wb' w是覆盖写入,b以二进制的方式 # discover(start_dir=文件所在路径, pattern='文件名称') dq=unittest.defaultTestLoader.discover(start_dir=Testcase_path,pattern='testcase.py') runner=HTMLTestRunner(stream=f, #接写入文件名 title='cms自动化测试报告', #报告标题 description='自动化测试运行情况如下:', #报告描述 tester='laoxiao') #测试人员 runner.run(dq) #运行报告写入内容 f.close() #关闭文件 def fsyj(): # SendMail(send_msg=文件, attachment=文件作附件) sm=SendMail(send_msg=file,attachment=file) sm.send_mail() if __name__ == '__main__': auto_run() # 调用函数,让它执行写入报告 fsyj() # 调用函数,让它执行发送邮件
=========================================================================
**第六个包 :testcase包**
在创建一个testcase用例包用来存放用例
编写测试用例
框架的思想:把整个用例进行拆分
mport unittest from UI_AUTO_PO.Public.Pages.basepage import * from UI_AUTO_PO.Public.Pages.element import * from UI_AUTO_PO.Public.Utils.readini import * #导入读取ini这个文件 from time import sleep class Cms_auto(unittest.TestCase): def setUp(self): self.p=Basepage() self.p.driver(webdriver.Chrome()) self.p.url(url) self.p.win() sleep(2) self.p.find_elem(Element.dwzh) self.p.skeys(user) self.p.find_elem(Element.dwmm) self.p.skeys(pwd) sleep(1) self.p.find_elem(Element.dwdlan) self.p.click() # 用户管理 def test001_yhgl(self): sleep(1) self.p.find_elem(Element.dwyhzx) self.p.click() self.p.wait(3) self.p.find_elem(Element.dwyhgl) self.p.click() sleep(2) self.p.find_elem(Element.dwframe1) self.p.frame() # 添加用户 def test002_add(self): self.test001_yhgl() sleep(1) self.p.find_elem(Element.dwtjyhan) self.p.click() sleep(2) self.p.find_elem(Element.dwframe2) self.p.frame() sleep(1) self.p.find_elem(Element.sryhm) self.p.skeys(Element.sjzh) self.p.find_elem(Element.srxb) self.p.wait(3) self.p.find_elem(Element.srdh) self.p.skeys(Element.sjhm) self.p.wait(3) self.p.find_elem(Element.sryx) self.p.skeys(Element.yx) self.p.wait(3) self.p.find_elem(Element.srzh) self.p.skeys(Element.sjzh) self.p.wait(3) self.p.find_elem(Element.srmm) self.p.skeys(Element.mm) self.p.wait(3) self.p.find_elem(Element.srqrmm) self.p.skeys(Element.mm) self.p.wait(3) self.p.find_elem(Element.qdan) self.p.click() sleep(2) self.p.unframe() sleep(1) self.p.find_elem(Element.dwframe1) self.p.frame() sleep(2) self.p.find_elem(Element.dy1) assert self.p.text()==Element.sjhm # # 查询用户 # def test003_query(self): # self.test001_yhgl() # sleep(2) # self.p.find_elem(('id','searchValue')) # self.p.skeys('longgang002') # self.p.wait(2) # self.p.find_elem(('id', 'searchBtn')) # self.p.click() # sleep(2) # self.p.find_elem(('xpath','//*[@id="sysUserTab"]/tr[1]/td[5]')) # assert self.p.text()=='18000000001' def tearDown(self): pass