python自动化测试—配置文件的使用
一、什么是配置文件?
配置文件示例
[mysql]
default-character-set = utf8 [mysqld]
port = 3306
basedir = c:\mysql-5.7.25-winx64\mysql-5.7.25-winx64
daradir = c:\mysql-5.7.25-winx64\mysql-5.7.25-winx64\data
max_connections = 200
character-set-server = utf8
default-storage-engine = INNODB
explicit_defaults_for_timestamp = true
为什么要做配置文件?
所有的代码和配置都变成模块化可配置化,这样就提高了代码的复用性,不用每次都去修改代码内部。
场景举例
1、多处地方需要使用同一个参数,这时候最好是配置化,这样改一处就可以了
2、如果是经常变化的变量,我们也可以做这个配置。---> 与参数化要区分开来
python中常见的配置文件格式
.ini、.conf、.cfg结尾的文件
配置对象
- section
- option
二、ConfigParser模块
掌握一些比较基础的用法:跟file文件一样,要先打开才能进行读取操作
实例化ConfigParse对象:cf = configParser.ConfigParser()
打开配置文件:cf.read(配置文件名称或者地址)
常用方法:
- read(filename) 直接读取文件内容
- sections() 得到所有的section,并以列表的形式返回
- options(section) 得到该section的所有option
- items(section) 得到该section的所有键值对
- get(section,option) 得到该section中option的值,返回类型为string
- getint(section,option) 得到该section中option的值,返回为int类型,还有相应的getboolean()和getfloat()
练习
import configparser
# 实例化ConfigParser对象
conf = configparser.ConfigParser()
# 打开配置文件
cf = conf.read("my.conf",encoding = 'utf8')
# 根据section和option得到option的值
a = conf.get('mysqld','port')
print(a) # 得到所有的section,并以列表的形式返回
b = conf.sections()
print(b)
# 得到该section的所有option
c = conf.options('mysqld')
print(c)
# 得到该section所有的键值对
d = dict(conf.items("mysql"))
print(d)
输出结果为:
封装一个读取配置文件的类
import configparser
"""
为什么要封装?
封装是为了使用起来更加方便,便于再次修改
封装的需求?
封装成什么样子才能达到我们的目的
封装的原则:
写死的固定数据(变量),可以封装成雷属性
实现某个功能的代码封装成方法
在各个办法中都要用到的数据,抽离出来作为实例属性
""" # 封装前 读取数据(三部曲)
# 实例化ConfigParser对象
# conf = configparser.ConfigParser()
# 打开配置文件
# conf.read("config.ini",encoding='utf8')
# # 根据section和option得到option的值
# conf.get('excel','file_name') class ReadConfig(configparser.ConfigParser): def __init__(self):
# 实例化对象
super().__init__()
# 加载文件
self.read(r"E:\python_api_test\API_Test_v4_config\conf\config.ini",encoding='utf8') conf = ReadConfig()
在其他模块调用封装好的配置文件时:from xxxx.xxxx.config import conf
三、将配置文件集成到单元测试中
1、项目结构
- common:这个目录用来存放的是自己封装的类
- conf:这个目录用来存放配置文件
- librarys:这个目录用来存放已封装好的模块(HTMLtestrunner、ddt)
- logs:这个目录用来存放日志文件
- data:这个目录用来存放excel的测试用例数据
- reposts:这个目录用来存放生成的的测试报告
- testcases:这个目录用来存放所有的测试用例模块
2、各项目层的结构图
3、各项目层的具体代码
common层(包括config.py文件、mylogging_v3.py文件、read_excel_data.py文件)
新建config.py文件
import configparser
"""
为什么要封装?
封装是为了使用起来更加方便,便于再次修改
封装的需求?
封装成什么样子才能达到我们的目的 封装的原则:
写死的固定数据(变量),可以封装成雷属性
实现某个功能的代码封装成方法
在各个办法中都要用到的数据,抽离出来作为实例属性
""" # 封装前 读取数据(三部曲)
# 实例化ConfigParser对象
# conf = configparser.ConfigParser()
# 打开配置文件
# conf.read("config.ini",encoding='utf8')
# # 根据section和option得到option的值
# conf.get('excel','file_name')
class ReadConfig(configparser.ConfigParser):
def __init__(self):
# 实例化对象
super().__init__()
# 加载文件
self.read(r"E:\python_api_test\API_Test_v4_config\conf\config.ini",encoding='utf8')
conf = ReadConfig()
新建mylogging_v3.py文件
import logging
from API_Test_v4_config.common.config import conf # 日志收集器的名称
logger_name = conf.get('log','logger_name')
# 日志收集器的级别
level = conf.get('log','level').upper()
# 输出到控制台的日志级别
sh_level = conf.get('log','sh_level').upper()
# 输出到文件的日志级别
fh_level = conf.get('log','fh_level').upper()
# 日志保存的文件
log_file_path = conf.get('log','log_file_path') class MyLogging(object):
def create_logger(*args,**kwargs):
# 创建自己的日志收集器
my_log = logging.getLogger(logger_name)
# 设置收集的日志等级,设置为DEBUG等级
my_log.setLevel(level)
# 日志输出渠道
# 创建一个日志输出渠道(输出到控制台),并且设置输出的日志等级为INFO以上
l_s = logging.StreamHandler()
l_s.setLevel(sh_level)
# 创构建一个日志输出渠道(输出到文件),并且设置输出的日志等级为DEBUG以上
l_f = logging.FileHandler(log_file_path,encoding='utf8')
l_f.setLevel(fh_level)
#将日志输出渠道添加到日志收集器中
my_log.addHandler(l_s)
my_log.addHandler(l_f)
# 设置日志输出的格式
ft = "%(asctime)s - [%(filename)s -->line:%(lineno)d] - %(levelname)s: %(message)s"
ft = logging.Formatter(ft)
# 设置控制台和日志文件输出日志的格式
l_s.setFormatter(ft)
l_f.setFormatter(ft)
return my_log def debug(self,msg):
self.my_log.debug(msg) def info(self,msg):
self.my_log.info(msg) def warning(self,msg):
self.my_log.warning(msg) def error(self,msg):
self.my_log.error(msg) def critical(self,msg):
self.my_log.critical(msg) #日志输出
m_log = MyLogging()
# 创建日志收集器
logger = m_log.create_logger()
新建read_excel_data.py文件
import openpyxl
class Case:
def __init__(self,arrts):
for item in arrts:
setattr(self,item[0],item[1])
class ReadExcel(object):
def __init__(self,filename,sheetname):
"""
定义需要打开的文件及表名
:param filename: 文件名
:param sheetname: 表名
"""
self.wb = openpyxl.load_workbook(filename) # 打开工作簿
self.sheet = self.wb[sheetname] # 选定表单
self.filename = filename # 特殊的魔术方法,在对象销毁之后执行的
def __del__(self):
# 关闭文件
self.wb.close()
def read_data_line(self):
#按行读取数据转化为列表
rows_data = list(self.sh.rows)
# print(rows_data)
# 获取表单的表头信息
titles = []
for title in rows_data[0]:
titles.append(title.value)
# print(titles)
#定义一个空列表用来存储测试用例
cases = []
for case in rows_data[1:]:
# print(case)
data = []
for cell in case: #获取一条测试用例数据
# print(cell.value)
data.append(cell.value)
# print(data)
#判断该单元格是否为字符串,如果是字符串类型则需要使用eval();如果不是字符串类型则不需要使用eval()
if isinstance(cell.value,str):
data.append(eval(cell.value))
else:
data.append(cell.value)
#将该条数据存放至cases中
# print(dict(list(zip(titles,data))))
case_data = dict(list(zip(titles,data)))
cases.append(case_data)
return cases def read_excel_obj_new(self,list1):
"""
按指定的列,读取excel中的数据,以列表的形式返回,列表中每个对象为一条测试用例,
Excel中的表头为对象的属性,对应的数据为属性值。
:param list1: list --->要读取的列[1,2,3...]
:return: type:list--->[case_obj1,case_obj2.......]
"""
# 从配置文件中读取的数据类型为string,需要转化为list
list1 = eval(list1)
# 判断传入的读取数据的列数是否为空,为空的话直接读取excel中所有的数据。
if list1 == []:
return self.read_data_line()
# 获取表里面的最大行数
max_row = self.sheet.max_row
# 定义一个空列表,用来存放测试用例数据
cases = []
# 定义一个空列表,用来存放表头数据
titles = []
# 遍历所有的行数据
for row in range(1,max_row+1):
case_data = []
if row != 1:
for column in list1:
info = self.sheet.cell(row,column).value
# print(info)
case_data.append(info)
case = list(zip(titles,case_data))
# print(case)
case_obj = Case(case)
cases.append(case_obj)
else:
for column in list1:
title = self.sheet.cell(row,column).value
titles.append(title)
if None in titles:
raise ValueError("表头的数据有显示为空")
return cases
def write_excel(self,row,column,msg):
#写入数据
self.sheet.cell(row=row,column=column,value=msg)
self.wb.save(self.filename)
conf层(config.ini文件--->配置文件)
新建config.ini文件
# log日志相关配置
[log]
# 日志收集器的名称
logger_name = my_log
# 日志收集器的级别
level = DEBUG
# 输出到控制台的日志级别
sh_level = DEBUG
# 输出到文件的日志级别()
fh_level = debug
# 日志保存的文件
log_file_path = E:\python_api_test\API_Test_v4_config\logs\log.log # 读取excel中测试用例数据相关的配置
[excel]
# 用例文件名称
file_name = E:\python_api_test\API_Test_v4_config\data\cases.xlsx
# sheet表单名称
sheet_name = Sheet1
# 读取表单中的列数(每条用例的数据) []空列表便是所有列
read_colums = [1,2,3] # 测试报告相关的配置
[report]
report_path = E:\python_api_test\API_Test_v4_config\reports\report.html
report_name = python接口自动化测试报告
report_tester = 测试
data层(cases.xlsx文件--->测试用例数据)
新建cases.xlsx文件
testcase层(register_testcase.py文件--->注册函数的测试用例)
新建register_testcase.py文件
import unittest
from API_Test_v4_config.register import register
from API_Test_v4_config.common.read_excel_data import ReadExcel
from ddt import ddt,data
from API_Test_v4_config.common.mylogging_v3 import logger
from API_Test_v4_config.common.config import conf # 配置文件中读取excel相关数据
file_name = conf.get('excel','file_name')
sheet_name = conf.get('excel','sheet_name')
read_colums = conf.get('excel','read_colums')
# 读取excel中的数据
wb = ReadExcel(file_name,sheet_name)
cases = wb.read_excel_obj_new(read_colums) @ddt
class RegisterTestCase(unittest.TestCase):
def setUp(self):
print("准备测试环境,执行测试用例之前会执行此操作")
def tearDown(self):
print("还原测试环境,执行完测试用例之后会执行此操作")
@data(*cases)
def test_register(self,case):
self.row = case.caseid + 1
res = register(*eval(case.data))
try:
self.assertEquals(eval(case.excepted),res)
except AssertionError as e:
res = "未通过"
logger.error(e)
raise e
else:
res = "通过"
logger.info("该条测试用例的测试结果为:{}".format(res))
finally:
# 调用写入数据的方法,在excel中回写测试用例的执行结果
wb.write_excel(row=self.row,column=4,msg=res) if __name__ == '__main__':
unittest.main()
最外面层(register.py文件--->需要测试的功能函数、 register_suites.py--->执行测试套件)
新建register.py文件
# 设计用例,对注册功能函数进行单元测试
users = [{'user': 'python18', 'password': ''}]
def register(username, password1, password2):
# 注册功能
for user in users: # 遍历出所有账号,判断账号是否存在
if username == user['user']:
# 账号存在
return {"code": 0, "msg": "该账户已存在"}
else:
if password1 != password2:
# 两次密码不一致
return {"code": 0, "msg": "两次密码不一致"}
else:
# 账号不存在 密码不重复,判断账号密码长度是否在 6-18位之间
if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:
# 注册账号
users.append({'user': username, 'password': password2})
return {"code": 1, "msg": "注册成功"}
else:
# 账号密码长度不对,注册失败
return {"code": 0, "msg": "账号和密码必须在6-18位之间"}
新建register_suites.py文件
import unittest
from HTMLTestRunnerNew import HTMLTestRunner
from API_Test_v4_config.testcases import register_testcase
from API_Test_v4_config.common.config import conf # 第二步:创建测试套件
suite = unittest.TestSuite()
# 第三步:将测试用例加载到测试套件中
loader = unittest.TestLoader()
# 通过测试用例类来添加测试用例
# suite.addTest(loader.loadTestsFromTestCase(RegisterTestCase))
# 通过模块来添加测试用例
suite.addTest(loader.loadTestsFromModule(register_testcase))
# 添加测试用例,通过路径加载测试用例目录下的所有模块
# suite.addTest(loader.discover("E:\\python_api_test\\API_Test_v4_config\\testcases"))
#第四步:执行测试套件,生成测试报告
# 读取配置文件中report相关的配置信息
report_path = conf.get("report",'report_path')
report_name = conf.get('report','report_name')
report_tester = conf.get('report','report_tester') with open(report_path,'wb') as f:
runner = HTMLTestRunner(
stream = f,
verbosity = 2,
title = 'python_18_report',
description = report_name,
tester = report_tester
)
runner.run(suite)
python自动化测试—配置文件的使用的更多相关文章
- Python自动化测试 -ConfigParser模块读写配置文件
C#之所以容易让人感兴趣,是因为安装完Visual Studio, 就可以很简单的直接写程序了,不需要做如何配置. 对新手来说,这是非常好的“初体验”, 会激发初学者的自信和兴趣. 而有些语言的开发环 ...
- 《自拍教程5》Python自动化测试学习思路
前提:熟悉测试业务及流程 任何Python自动化测试的前提,都是必须先熟悉实际测试业务. 任何脱离实际测试业务的自动化都是噱头且无实际意义! 测试的基本流程基本是: 测试需求分析,测试用例设计与评审, ...
- Python自动化测试面试题-Selenium篇
目录 Python自动化测试面试题-经验篇 Python自动化测试面试题-用例设计篇 Python自动化测试面试题-Linux篇 Python自动化测试面试题-MySQL篇 Python自动化测试面试 ...
- python自动化测试(2)-自动化基本技术原理
python自动化测试(2) 自动化基本技术原理 1 概述 在之前的文章里面提到过:做自动化的首要本领就是要会 透过现象看本质 ,落实到实际的IT工作中就是 透过界面看数据. 掌握上面的这样的本领 ...
- python自动化测试(4)-使用第三方python库技术实现
python自动化测试(4)-使用第三方python库技术实现 1 概述 关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 ...
- python自动化测试(3)- 自动化框架及工具
python自动化测试(3) 自动化框架及工具 1 概述 手续的关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 后面所谈到 ...
- (学习网址)Python 自动化测试
1.Python自动化测试地址 http://www.wtoutiao.com/author/python-selenium.html 2.unittest参考网址: 1)python自动化测试报告H ...
- python 自动化测试资料
python 自动化测试资料: http://yunpan.cn/QXVvwVJsAsPnb
- selenium + python 自动化测试环境搭建
selenium + python 自动化测试 —— 环境搭建 关于 selenium Selenium 是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操 ...
随机推荐
- zeppelin安装使用
官网:http://zeppelin-project.org/ 代码:https://github.com/NFLabs/zeppelin 使用:按照官网的视频操作一遍,应该就懂了http://y ...
- if && grep
if 条件 then Command else Command fi 别忘了这个结尾 ——————— ...
- Leetcode: 二分搜索法
package com.LeetCode; /** * 算法:二分搜索法查找一个值,并返回索引值 * https://leetcode.com/problems/search-insert-posit ...
- [mysql]设置创建时间,更新时间未生效
问题描述: 新增一条case,create_time没有自动生成创建时间,值为空 原因 : create_time字段类型是DateTime(错误)而不是TIMESTAMP(正确) 解决办法: 把c ...
- WPF prism 类、属性和方法的导入和导出
学习Prism一定要掌握依赖注入的应用,只有了解了Prism的依赖注入才能更好的使用Prism提升应用开发的架构. 首先说明Prism依赖注入有两种方式及MEF和Unity ,在Prism中是两个没有 ...
- 我们公司的delphi代码(胆不是我写的!),看看,你觉得怎么样
unit unt_LotBill_dyc; interface uses windows, SysUtils, Classes, ComCtrls, Forms, Controls, StrUtils ...
- Pytorch调整学习率
每隔一定的epoch调整学习率 def adjust_learning_rate(optimizer, epoch): """Sets the learning rate ...
- 接口自动化--数据加密之AES
在接口测试中,会遇到加密的请求数据,例如:常用的base64加密,AES加密,在这里,简述用Python转化AES的加密方法 原理 官网链接:https://pycryptodome.readthed ...
- WAMP中的mysql设置密码
为WAMP中的mysql设置密码密码 WAMP安装好后,mysql密码是为空的,那么要如何修改呢?其实很简单,通过几条指令就行了,下面我就一步步来操作. 1.首先,通过WAMP打开mysql控制台. ...
- Python常用库整理
Python常用库整理 Python中到底有哪些库会让程序员爱不释手?以至于一次上瘾,造成永久性伤害(这句话好像在哪里见过),今天我们就来整理一番这样的库,欢迎各位在评论区或者私信我添加或者修改相关库 ...