python操作excel
openpyxl
-
前置说明
- 安装openpyxl
- 只支持.xlsx后缀
-
创建excel
- 手动创建:日常手动创建,双击excel图标
- 代码创建:后面讲
-
打开excel
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)
-
数据从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 <class 'int'> 分数是: {"语文":90,"数字":98,"生物":78} <class 'str'> 不及格率: 0.3 <class 'float'> 住址是: 中国上海 <class 'str'>
-
eval() 把数据类型转换为原本的类型(仅限被转为字符串)
s="True" #布尔值转为字符串 print(type(s)) #<class 'str'> a=eval(s)#使用eval函数,将字符串类型转为原来的布尔类型 print(type(a)) #<class 'bool'>
-
封装一个获取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的一个可配置性
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)) #<class 'str'> res_2=cf.get("PYTHON11", "num") print(type(res_2)) #<class 'str'> #使用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工具类要加以修改,加入读取配置文件
这样根据给配置文件button配置不同的值,all或者case_id的列表,run不同的数据。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())
- tools文件夹中写入配置文件