python操作excel
openpyxl
-
前置說明
- 安裝openpyxl
- 只支持.xlsx后綴
-
創(chuàng)建excel
- 手動創(chuàng)建:日常手動創(chuàng)建,雙擊excel圖標(biāo)
- 代碼創(chuàng)建:后面講
-
打開excel
imagefrom 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
-
數(shù)據(jù)從excel中拿出來是什么類型
#數(shù)據(jù)從excel中拿出來是什么類型 print("學(xué)號是:",sheet.cell(1,1).value,type(sheet.cell(1,1).value)) print("分?jǐn)?shù)是:",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))結(jié)果是:數(shù)字還是數(shù)字,其他都是字符
學(xué)號是: 18 <class 'int'> 分?jǐn)?shù)是: {"語文":90,"數(shù)字":98,"生物":78} <class 'str'> 不及格率: 0.3 <class 'float'> 住址是: 中國上海 <class 'str'> -
eval() 把數(shù)據(jù)類型轉(zhuǎn)換為原本的類型(僅限被轉(zhuǎn)為字符串)
s="True" #布爾值轉(zhuǎn)為字符串 print(type(s)) #<class 'str'> a=eval(s)#使用eval函數(shù),將字符串類型轉(zhuǎn)為原來的布爾類型 print(type(a)) #<class 'bool'> -
封裝一個獲取excel值的工具類
-
方法一:把數(shù)據(jù)一次取出,調(diào)用一次取出sheet所有數(shù)據(jù)(建議使用)
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=[] #每條數(shù)據(jù)要存在列表里 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("測試數(shù)據(jù):",ex.get_data()) 方法二:數(shù)據(jù)需要的時候再調(diào)用,調(diào)用一次取出一個單元格數(shù)據(jù)
-
```
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: 返回對應(yīng)單元格的值
"""
wb=load_workbook(self.file_name)
sheet=wb[self.sheet_name]
return sheet.cell(i,j).value
def get_max_row(self):
"""
:return: sheet的最大行數(shù)
"""
return self.sheet_obj.max_row
def get_max_col(self):
"""
:return: sheet的最大列數(shù)
"""
return self.sheet_obj.max_column
if __name__ == '__main__': #測試
do=DoExcel("test.xlsx","test001")
print(do.get_excel(1,1))
```
ddt
安裝ddt
-
ddt+unittest進(jìn)行數(shù)據(jù)處理
裝飾器,暫時不用過多了解,不影響函數(shù)的情況下運行
-
ddt示例
-
@ddt裝飾測試類 -
@data傳入數(shù)據(jù) -
@unpack針對拿到的每一條數(shù)據(jù),根據(jù)逗號進(jìn)行拆分
from ddt import ddt,unpack,data #導(dǎo)入ddt import unittest test_data=[1,4] #測試數(shù)據(jù) 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) #裝飾測試方法,拿到幾條數(shù)據(jù)執(zhí)行幾條用例 #不定長參數(shù),俗稱:脫外套 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 #針對拿到的每一條數(shù)據(jù),根據(jù)逗號進(jìn)行拆分, def test_print_data_03(self,a,b): #參數(shù)個數(shù)對應(yīng)@npack拆分的個數(shù),否則會報錯 print("a:",a) print("b:",b) # 輸出: # a: 3 b: 4 # a: 2 b: 3 @data(*test_param) @unpack #對于每一條測試用例的數(shù)據(jù)不等長時,可以采用默認(rèn)值為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 #對字典進(jìn)行unpack,參數(shù)名與你的字典key對應(yīng) def test_print_data_05(self,no,name): print("no:",no) print("name:",name)- 使用unpack,data里的參數(shù)記得加*
- 參數(shù)數(shù)據(jù)過長時,不建議用
@unpack,@data拿到后根據(jù)索引取值 - 光標(biāo)放在代碼最后面再run,不然會報錯
- 對字典進(jìn)行unpack,參數(shù)名與你的字典key對應(yīng)
-
DDT與excel結(jié)合使用
- 加載測試用例時,要使用TestLoader方法加載
總結(jié)unittest+excel
- 兩種方式
- 超繼承
- ddt
- 思路
- 自己寫的類
- unittest單元測試:實現(xiàn)對自己寫的類的測試
- TestCase測試用例:self.assert斷言、異常處理
- 參數(shù)化:數(shù)據(jù)可以寫在代碼里,也可以寫在excel里,excel使用openpyxl
- 處理數(shù)據(jù)寫成類
class GetExcel:
- 處理數(shù)據(jù)寫成類
- 數(shù)據(jù)與unittest結(jié)合起來
- 超繼承(原理要懂)
- 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"):
"""
約定參數(shù)button,默認(rèn)值為all。
如果button值為“all”,則表示運行所有的case;
如果button的值為一個case_id的列表,按照列表里的case_id進(jìn)行運行。
"""
wb=load_workbook(self.file_name)
sheet=wb[self.sheet_name]
test_data=[] #每條數(shù)據(jù)要存在列表里
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值進(jìn)行判斷
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("測試數(shù)據(jù):",ex.get_data()) #所有數(shù)據(jù)
print("測試數(shù)據(jù):", ex.get_data([1,3])) #第一條、第三條測試數(shù)據(jù)
配置文件
平常工作中可能會常見到.properties .config .ini .log4j(.log4j是java中的配置文件,python不用)結(jié)尾的文件,這些都是配置文件。python中有configparser模塊可以去讀取配置信息
-
配置文件的規(guī)范
- 新建一個文件以
.config結(jié)尾,.properties、.ini都可以 - section 片段,配置文件中用
[]區(qū)分,表示不同區(qū)域的數(shù)據(jù) - option=value,鍵值對,相當(dāng)于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") #獲取配置文件的數(shù)據(jù) # 方法一 res_1=cf.get("BUTTON","button") #(section,option)獲取對應(yīng)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', '小月')] -
數(shù)據(jù)類型
直接獲取的數(shù)據(jù)類型都是字符串,使用eval()轉(zhuǎn)換為原始數(shù)據(jù)類型
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()轉(zhuǎn)換為原始數(shù)據(jù)類型 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工具類要加以修改,加入讀取配置文件
這樣根據(jù)給配置文件button配置不同的值,all或者case_id的列表,run不同的數(shù)據(jù)。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=[] #每條數(shù)據(jù)要存在列表里 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("測試數(shù)據(jù):",ex.get_data())
- tools文件夾中寫入配置文件