python操作excel
openpyxl
前置说明
安装openpyxl
只支持.xlsx后缀
创建excel
手动创建:日常手动创建,双击excel图标
代码创建:后面讲
打开excel
image
from openpyxl import load_workbook
# 1.打开excel
wb=load_workbook("test.xlsx")
# 2.定位表单
sheet=wb["test001"] #必须传入表单名,返回表单对象
# 3.定位但单元格 行列值
value=sheet.cell(1,1).value #第1行第1列的单元格.值
#打印单元格的值
print(value)
#最大行
print("最大行:",sheet.max_row)
#最大列
print("最大列:",sheet.max_column)
image
数据从excel中拿出来是什么类型
#数据从excel中拿出来是什么类型
print("学号是:",sheet.cell(1,1).value,type(sheet.cell(1,1).value))
print("分数是:",sheet.cell(1,2).value,type(sheet.cell(1,2).value))
print("不及格率:",sheet.cell(1,3).value,type(sheet.cell(1,3).value))
print("住址是:",sheet.cell(1,4).value,type(sheet.cell(1,4).value))
结果是:数字还是数字,其他都是字符
学号是: 18
分数是: {"语文":90,"数字":98,"生物":78}
不及格率: 0.3
住址是: 中国上海
eval() 把数据类型转换为原本的类型(仅限被转为字符串)
s="True" #布尔值转为字符串
print(type(s)) #
a=eval(s)#使用eval函数,将字符串类型转为原来的布尔类型
print(type(a)) #
封装一个获取excel值的工具类
方法一:把数据一次取出,调用一次取出sheet所有数据(建议使用)
from openpyxl import load_workbook
class GetExcel:
def __init__(self,file_name,sheet_name):
self.file_name=file_name
self.sheet_name=sheet_name
def get_data(self):
wb=load_workbook(self.file_name)
sheet=wb[self.sheet_name]
test_data=[] #每条数据要存在列表里
for i in range(1, sheet.max_row+1):
sub_data={}
sub_data["age"]=sheet.cell(i,1).value
sub_data["score"]=sheet.cell(i,2).value
sub_data["percent"]=sheet.cell(i,3).value
sub_data["local"]=sheet.cell(i,4).value
test_data.append(sub_data)
return test_data
ex=GetExcel("test.xlsx","test001")
print("测试数据:",ex.get_data())
方法二:数据需要的时候再调用,调用一次取出一个单元格数据
```
from openpyxl import load_workbook
class DoExcel:
"""
获取excel单元格的值
"""
def __init__(self,file_name,sheet_name):
"""
:param file_name: excel文件名
:param sheet_name: sheet名
"""
self.file_name=file_name
self.sheet_name=sheet_name
def get_excel(self,i,j):
"""
:param i: 第几行
:param j: 第几列
:return: 返回对应单元格的值
"""
wb=load_workbook(self.file_name)
sheet=wb[self.sheet_name]
return sheet.cell(i,j).value
def get_max_row(self):
"""
:return: sheet的最大行数
"""
return self.sheet_obj.max_row
def get_max_col(self):
"""
:return: sheet的最大列数
"""
return self.sheet_obj.max_column
if __name__ == '__main__': #测试
do=DoExcel("test.xlsx","test001")
print(do.get_excel(1,1))
```
ddt
安装ddt
ddt+unittest进行数据处理
装饰器,暂时不用过多了解,不影响函数的情况下运行
ddt示例
@ddt 装饰测试类
@data 传入数据
@unpack 针对拿到的每一条数据,根据逗号进行拆分
from ddt import ddt,unpack,data #导入ddt
import unittest
test_data=[1,4] #测试数据
test_body=[[3,4],[2,3]]
test_param=[[3,4],[2,3,7]]
test_dict=[{"no":1,"name":"anny"},{"no":2,"name":"liu"}]
@ddt #装饰测试类
class TestMath(unittest.TestCase):
@data(test_data)
def test_print_data(self,item): #一条用例
print("item:",item) #item: [1, 4]
@data(*test_data) #装饰测试方法,拿到几条数据执行几条用例
#不定长参数,俗称:脱外套
def test_print_data_01(self,item):
print("item:", item) # item: 1 item: 4
@data(*test_body) #脱外套只脱一层
def test_print_data_02(self,item):
print("item:",item) #item: [3, 4] item: [2, 3]
@data(*test_body)
@unpack #针对拿到的每一条数据,根据逗号进行拆分,
def test_print_data_03(self,a,b): #参数个数对应@npack拆分的个数,否则会报错
print("a:",a)
print("b:",b)
# 输出:
# a: 3 b: 4
# a: 2 b: 3
@data(*test_param)
@unpack
#对于每一条测试用例的数据不等长时,可以采用默认值为None的方式接收避免报错
def test_print_data_04(self,a=None,b=None,c=None):
print("a:",a)
print("b:",b)
print("c:",c)
# 输出:
# a: 3 b: 4 c: None
# a: 2 b: 3 c: 7
@data(*test_dict)
@unpack
#对字典进行unpack,参数名与你的字典key对应
def test_print_data_05(self,no,name):
print("no:",no)
print("name:",name)
使用unpack,data里的参数记得加*
参数数据过长时,不建议用@unpack,@data拿到后根据索引取值
光标放在代码最后面再run,不然会报错
对字典进行unpack,参数名与你的字典key对应
DDT与excel结合使用
加载测试用例时,要使用TestLoader方法加载
总结unittest+excel
两种方式
超继承
ddt
思路
自己写的类
unittest单元测试:实现对自己写的类的测试
TestCase测试用例:self.assert断言、异常处理
参数化:数据可以写在代码里,也可以写在excel里,excel使用openpyxl
处理数据写成类 class GetExcel:
数据与unittest结合起来
超继承(原理要懂)
ddt (推荐使用)
配置文件
用例的可配置
有时,我们需要run不同程度的case、不同模块的case,所以需要case的一个可配置性
image
from openpyxl import load_workbook
class GetExcel:
def __init__(self,file_name,sheet_name):
self.file_name=file_name
self.sheet_name=sheet_name
def get_data(self,button="all"):
"""
约定参数button,默认值为all。
如果button值为“all”,则表示运行所有的case;
如果button的值为一个case_id的列表,按照列表里的case_id进行运行。
"""
wb=load_workbook(self.file_name)
sheet=wb[self.sheet_name]
test_data=[] #每条数据要存在列表里
for i in range(2, sheet.max_row+1): #第一行是title,所以从第二行开始
sub_data={}
sub_data["case_id"] = sheet.cell(i, 1).value
sub_data["mouble"] = sheet.cell(i, 2).value
sub_data["age"]=sheet.cell(i,3).value
sub_data["score"]=sheet.cell(i,4).value
sub_data["percent"]=sheet.cell(i,5).value
sub_data["local"]=sheet.cell(i,6).value
test_data.append(sub_data)
#对传入的button值进行判断
if button == "all":
finally_data=test_data
else: #[1,2,3,4]
finally_data=[]
for item in test_data:
if item["case_id"] in button:
finally_data.append(item)
return finally_data
if __name__ == '__main__':
ex=GetExcel("testdata.xlsx","Sheet1")
print("测试数据:",ex.get_data()) #所有数据
print("测试数据:", ex.get_data([1,3])) #第一条、第三条测试数据
配置文件
平常工作中可能会常见到.properties .config .ini .log4j(.log4j是java中的配置文件,python不用)结尾的文件,这些都是配置文件。python中有configparser模块可以去读取配置信息
配置文件的规范
新建一个文件以.config结尾,.properties、.ini都可以
section 片段,配置文件中用[]区分,表示不同区域的数据
option=value,键值对,相当于key:value
#case.config文件
[BUTTON] #section
button=all #option=value
[PYTHON11] #section
num=30 #option、value
monitor=小月 #option=value
读取配置文件
import configparser
cf=configparser.ConfigParser()
cf.read("case.config",encoding="utf-8")
#获取配置文件的数据
# 方法一
res_1=cf.get("BUTTON","button") #(section,option)获取对应option的value
print(res_1) #all
# 方法二
res_2=cf["BUTTON"]["button"]
print(res_2) #all
#获取所有的section
res_3=cf.sections()
print(res_3) #['BUTTON', 'PYTHON11']
#获取option和value,每对以元组形式返回在一个列表里
res_4=cf.items("PYTHON11")
print(res_4) #[('num', '30'), ('monitor', '小月')]
数据类型
直接获取的数据类型都是字符串,使用eval()转换为原始数据类型
res_1 = cf.get("BUTTON", "button")
print(type(res_1)) #
res_2=cf.get("PYTHON11", "num")
print(type(res_2)) #
#使用eval()转换为原始数据类型
res_3 =cf.get("python11", "num")
print(type(eval(res_3)))
封装为一个工具类
tools文件夹中写入配置文件case.config
[BUTTON]
button=all
#button=[1,2]
tools文件夹中写一个工具类class ReadConfig:
import configparser
class ReadConfig:
def read_config(self,file_name,section,option):
cf=configparser.ConfigParser()
cf.read(file_name,encoding="utf-8")
return eval(cf.get(section,option))
if __name__ == '__main__':
rc=ReadConfig()
res=rc.read_config("case.config","BUTTON","button")
print(res) #all
原来的do_excel工具类要加以修改,加入读取配置文件
from openpyxl import load_workbook
from API_AUTO.tools import read_config
class GetExcel:
def __init__(self,file_name,sheet_name):
self.file_name=file_name
self.sheet_name=sheet_name
def get_data(self):
#读取配置文件
button=read_config.ReadConfig().read_config("case.config","BUTTON","button")
wb=load_workbook(self.file_name)
sheet=wb[self.sheet_name]
test_data=[] #每条数据要存在列表里
for i in range(2, sheet.max_row+1):
sub_data={}
sub_data["case_id"] = sheet.cell(i, 1).value
sub_data["mouble"] = sheet.cell(i, 2).value
sub_data["age"]=sheet.cell(i,3).value
sub_data["score"]=sheet.cell(i,4).value
sub_data["percent"]=sheet.cell(i,5).value
sub_data["local"]=sheet.cell(i,6).value
test_data.append(sub_data)
if button == "all":
finally_data=test_data
else: #[1,2,3,4]
finally_data=[]
for item in test_data:
if item["case_id"] in button:
finally_data.append(item)
return finally_data
if __name__ == '__main__':
ex=GetExcel("testdata.xlsx","Sheet1")
print("测试数据:",ex.get_data())
这样根据给配置文件button配置不同的值,all或者case_id的列表,run不同的数据。