一、总体的框架图:
'''ini是一种配置文件
在ui自动化测试中配置文件的种类
ini、Excel、.py、yaml、txt'''
'''1、先创建一个discz项目
在创建一个cofing包==存放所有配置文件信息(比如项目路径和数据,用例的路径)
可以封装路径
在创建一个Data包==放数据(测试数据)
在Data包中创建一个TestData目录(放测试数据)
测试环境的一些url地址和账号密码可以放在TestDta中
在创建一个repot包==存放测试报告
在repot包中创建一个Testrepot目录(存放报告)
在创建一个public公共公开的包(存放一些功能用例)
在public包中创建pages存放元素层流程层(封装所有页面的公共方法,基类)
在public包中创建utils包(处理公共类公共函数都存放在此)
可以在utils中来读取pages中封装的登录的流程(封装读取ini文件或者EXCEL表格的工具类和工具函数
在创建一个TestCase用例包用来存放用例
编写测试用例
在创建一个run_all用来运行
通过运行测试用例中封装好的用例在运行然后在repot中生成测试报告
框架的思想:把整个用例进行拆分
==========================================================
一、config
配置config包
1 2 3 4 5 6 7 8 9 10 | [project] project_path = C:\Users\Administrator\PycharmProjects\untitled1\discuz [env] url = http: / / cms.duoceshi.cn / cms / manage / login.do username = admin password = 123456 [email] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import os import time from discuz.public.utils.ReadConfigIni import ReadConfigIni #导入ReadConfigIni类 #获取项目的绝对路径 project_path = os.path.dirname(os.path.dirname(__file__)) print (project_path) #项目绝对路径 project_path = os.path.dirname(os.path.dirname(__file__)) print (project_path) #config绝对路径 config_path = os.path.join(project_path, 'cofing' ) print (config_path) #data绝对路径 data_path = os.path.join(project_path, 'data' ) # print(data_path) #pages绝对路径 pages_path = os.path.join(project_path, 'public' , 'pages' ) print (pages_path) #utils绝对路径 utils_path = os.path.join(project_path, 'public' , 'utils' ) print (utils_path) #repot绝对路径 repot_path = os.path.join(project_path, 'repot' ) # print(repot_path) #run绝对路径 run_path = os.path.join(project_path, 'run' ) print (run_path) #testcase绝对路径 testcase_path = os.path.join(project_path, 'testcase' ) print (testcase_path) #以上路径我们进阶下就ok |
==========================================================
二、data
========================================================
三、public
BaseTestCase.py文件
pages:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | from selenium import webdriver #导入selenium 引用webdrvier方法 import time #导入time模块 import unittest #导入单元测试框架 class BaseTestcase(unittest.TestCase): #所有页面的公共方法都封装在BaseTestcase这个类中、简称基类一切类的父类需求打开浏览器-输入网址-定位百度输入框元素-输入内容-点击按钮''' @classmethod #类的开始 def set_drvier( cls ,driver): #设置drvier对象,需要保证每个用例的执行都是用的同一个drvier对象java当中的设计模块式-单例模式''' cls .driver = driver #cls.drvier就是BaseTestcase这个类的类变量''' # driver=webdriver.Chrome()#为了调试 @classmethod def get_drvier( cls ): return cls .driver @classmethod def find_element( cls ,element): #封装定位元素的工具方法包含id name class link xpath css等''' # baidu=('id','kw')==传元组 type = element[ 0 ] #取element索引为0 value = element[ 1 ] #取element索引为1 try : #尝试运行这些代码如果代码报错抛异常 if type = = 'id' or type = = 'Id' or type = = 'ID' : elem = cls .driver.find_element_by_id(value) elif type = = 'name' or type = = 'Name' or type = = 'NAME' : elem = cls .driver.find_element_by_name(value) elif type = = 'class' or type = = 'Class' or type = = 'CLASS' : elem = cls .driver.find_element_by_class_name(value) elif type = = 'xpath' or type = = 'Xpath' or type = = 'XPATH' : elem = cls .driver.find_element_by_xpath(value) elif type = = 'css' or type = = 'Css' or type = = 'CSS' : elem = cls .driver.find_element_by_css_selector(value) else : raise NameError( '请输入正确的参数' ) except Exception: #如果上面代码定位元素出错,然后这里就会捕捉异常信息 raise NameError( '捕捉异常' + str (element)) return elem #把元素返回上去,如果没有抛异常则把属性返回给类函数调用处本身 @classmethod def send_keys( cls ,element,text): #封装一个输入 element.send_keys(text) #找到元素后通过.send_keys输入text内容 @classmethod def click( cls ,element): #封装一个click点击 element.click() @classmethod def sleep( cls ,sec): #封装了一个线程等待 return time.sleep(sec) @classmethod def max_window( cls ): #封装了一个窗口最大化 return cls .driver.maximize_window() @classmethod def wait( cls ,time): return cls .driver.implicitly_wait(time) @classmethod #封装一个关闭当前浏览器 def close( cls ): return cls .driver.close() |
==============================================================
Page_Element.py
'''
此模块是为了存放所有页面的元素
Java当中的设计模式:
PO设计模式 ==》全称叫做page object(页面对象模型)
把所有页面上的元素都作为对象的或者类的属性
PO的优势:
1.把元素和流程、案例可以分离
2.让代码的耦合度降低
3.可以让代码更加容易维护
'''
class Page_Element:
#登录模块
userName = ('id','ls_username') #用户名
passWord = ("id","ls_password") #密码
loginBtn = ("css",".pn") #登录按钮
loginOut = ("link","退出") #定位到退出
#模块管理
moduleManage = ("link","模块管理") #定位到模块管理
submit = ("id","submit") #定位到提交
==================================================================
utils:
Login_Data.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ''' 此模块是用来读取Excel文件中的内容 ''' from discuz.public.utils.ReadExcel import ReadExcel #导入ReadExcel类 class Login_Data: @staticmethod def get_url(): ''' 获取测试的url地址 根据ReadExcel类创建对象需要传入2个参数:1个是文件名称、1个是哪一个Sheet页面 Sheet1中的S是一个大写的S''' url = ReadExcel( "Data.xlsx" , "Sheet1" ).read_excel( 1 , 0 ) return url #http://192.168.254.129/bbs @staticmethod def get_username(): '''获取测试的账号''' username = ReadExcel( "Data.xlsx" , "Sheet1" ).read_excel( 1 , 1 ) return username #admin @staticmethod def get_password(): '''获取测试的密码''' password = ReadExcel( "Data.xlsx" , "Sheet1" ).read_excel( 1 , 2 ) return int (password) #把浮点型数据转换为int整型 123456 if __name__ = = '__main__' : print (Login_Data.get_url()) print (Login_Data.get_username()) print (Login_Data.get_password()) |
ReadConfigIni.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #在python当中有一个模块configparser是用来处理ini文件 #pip install configparser #第一种安装方式 import configparser from discuz.config.globalconfig import * class ReadConfigIni: def __init__( self ,filename): ''' 这个工具类主要是用来读取ini文件的 :param filename: ''' self .cf = configparser.ConfigParser() #创建configparser类的对象 self .cf.read(filename) def getConfigValue( self ,config,name): #获取config 文件的内容 ''' 读取section和option对应的value值 ''' value = self .cf.get(config,name) return value r = ReadConfigIni(os.path.join(config_path, 'cofingini' )) #传值,我们要去config文件中config的文件 print (r.getConfigValue( "path" , "project_path" )) |
ReadExcel.py
#此模块是用来读取Excel文档的
#pip install xlrd
import xlrd
import os
from discuz.config.globalconfig import data_path #导入data数据的绝对路径
#data_path的结果为:E:\pycharm\discuz\Data\TestData
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(data_path,"sheet1")
print(r.read_excel(1,0))
==========================================================
report
========================================================
1 2 3 4 5 6 7 8 9 10 11 12 13 | import unittest from discuz.run_all.HTMLTestRunner3_New import HTMLTestRunner from discuz.TestCase.login import TestLogin from discuz.config.globalconfig import * def auto_run(): # suite = unittest.TestSuite() #创建一个套件、容器 用来装测试用例 # suite.addTests([TestLogin('testLogin')]) discore = unittest.defaultTestLoader.discover(start_dir = project_path,pattern = 'log*.py' ) f = open (port_path, "wb" ) run = HTMLTestRunner(stream = f,title = 'Discuz论坛项目UI自动化测试报告' ,description = '用例执行情况如下' ,tester = '小钱' ) run.run(discore) if __name__ = = '__main__' : auto_run() |
=======================================================
TestCase
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | from discuz.public.pages.BaseTestCase import BaseTestcase #导入BaseTestCase类 import unittest from selenium import webdriver from discuz.public.utils.Login_Data import Login_Data as login #导入Login_Data类并且取别名为login from discuz.public.pages.Page_Element import Page_Element as p #导入Page_Element类并且取别名为p url = login.get_url() #拿到了url地址 username = login.get_username() #拿到了username的值为admin pwd = login.get_password() #拿到了密码 123456 class TestLogin(BaseTestcase): @classmethod def setUpClass( cls ): '''测试之前的准备工作''' driver = webdriver.Chrome() #创建一个driver对象 BaseTestcase.set_drvier(driver) #通过父类调用set_driver类方法把driver对象传给父类作为类变量 @classmethod def tearDownClass( cls ): BaseTestcase.sleep( 3 ) # def testLogin( self ): driver = BaseTestcase.get_drvier() #通过父类调用get_driver类方法拿到driver对象==》打开的浏览器 driver.get(url) #打开论坛的地址 driver.maximize_window() #最大化窗口 BaseTestcase.wait( 20 ) #设置隐式等待 #1.输入用户名 userName = BaseTestcase.find_element(p.userName) BaseTestcase.send_keys(userName,username) #2.输入密码 passWord = BaseTestcase.find_element(p.passWord) BaseTestcase.send_keys(passWord,pwd) #3.点击登录按钮 loginBtn = BaseTestcase.find_element(p.loginBtn) BaseTestcase.click(loginBtn) #4.关闭当前浏览器 # BaseTestcase.sleep(4) #等待4秒 # BaseTestcase.close() #关闭当前浏览器 if __name__ = = '__main__' : unittest.main() |
==========================================================================
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架