基於Python的介面自動化-讀寫excel檔案

那年故鄉的明月發表於2021-01-15

引言

        使用python進行介面測試時常常需要介面用例測試資料、斷言介面功能、驗證介面響應狀態等,如果大量的介面測試用例指令碼都將介面測試用例資料寫在指令碼檔案中,這樣寫出來整個介面測試用例指令碼程式碼將看起來很冗餘和難以清晰的閱讀以及維護,試想如果所有的介面測試資料都寫在程式碼中,介面引數或者測試資料需要修改,那不得每個程式碼檔案都要一一改動?。因此,這種不高效的模式不是我們想要的。所以,在自動化測試中就有個重要的思想:測試資料和測試指令碼分離,也就是測試指令碼只有一份,其中需要輸入資料的地方會用變數來代替,然後把測試輸入資料單獨放在一個檔案中,這個存放測試輸入資料的檔案,通常是表格的形式或者其他格式檔案,如excel檔案、json檔案、xml檔案、txt文字檔案等等。在python進行介面自動化測試時,為了方便管理和儲存測試用例資料,一般將測試資料編寫儲存在excel檔案中,測試指令碼通過讀取excel檔案來實現測試資料載入,並執行得出測試用例資料執行的結果,並回寫測試結果到excel檔案中,這樣就實現了測試指令碼和資料的分離。而python操作excel檔案的讀寫,這裡需要安裝並引入第三方模組:xlrd和xlwt以及xlutils,xlrd為讀取excel模組,xlwt為向excel寫資料的模組,xlutils可以複製excel並修改excel中的資料。下面就具體介紹xlrd和xlwt操作excel檔案提供的通用方法和技巧,以及xlutils如何複製和修改excel,達到操作excel讀寫的目的。

一、xlrd、xlwt以及xlutils安裝

1.使用pip安裝

pip install xlrd 
pip install xlwt
pip install xlutils

2.在PyCharm中安裝

 直接檢索需要安裝的模組名稱即可,如xlrd:

二、xlrd操作excel檔案的資料讀取

新建一個excel檔案,檔名稱:excel_test.xlsx,檔案編輯有兩個sheet表,內容如下:

sheet1:

 sheet2:

 (1)開啟excel檔案,獲取excel的sheet名

編輯如下程式碼:

import xlrd
file = xlrd.open_workbook("excel_test.xlsx")
all_sheet = file.sheet_names()  # 獲取所有的工作簿名
sheet_name1 = file.sheet_names()[0]  # 通過sheet下標獲取,第一個sheet下標為0
sheet_name2 = file.sheet_by_index(0).name # 通過sheet索引獲取sheet名
print(all_sheet)
print(sheet_name1)
print(sheet_name2)
-----------------------------------------
# 返回結果
['員工資訊表', 'api測試用例']
員工資訊表
員工資訊表

 (2)獲取sheet工作表頁的物件

程式碼示例:

import xlrd
file = xlrd.open_workbook("excel_test.xlsx")
sheet_name1 = file.sheet_names()[0]
sheet1_obj = file.sheet_by_name(sheet_name1)  # 通過sheet名獲取sheet物件
sheet2_obj = file.sheet_by_index(1) # 通過sheet索引獲取sheet物件
print(sheet1_obj)
print(sheet2_obj)
------------------------------------
# 返回結果
<xlrd.sheet.Sheet object at 0x0000000002AA09B0>
<xlrd.sheet.Sheet object at 0x0000000002AA0978>

(3)獲取sheet工作表的行、列數,整行、整列資料,具體的單元格資料

程式碼示例:

import xlrd
file = xlrd.open_workbook("excel_test.xlsx")
sheet = file.sheet_by_index(0) # 通過sheet索引獲取sheet物件
nrows = sheet.nrows    # 獲取行數
ncols = sheet.ncols    # 獲取列數
nrows_data = sheet.row_values(1)   # 獲取第二行資料,返回的是列表
ncols_data = sheet.col_values(0)   # 獲取第一列資料,返回的是列表
cell = sheet.cell(1,2)             # 獲取單元格資料,如第二行,第三列資料
print(nrows)
print(ncols)
print(nrows_data)
print(ncols_data)
print(cell)
-------------------------------
# 返回結果
6
5
['王五', '男', 32883.0, 'java開發工程師', 233.0]
['姓名', '王五', '李四', '張三', '小紅', '小明']
xldate:32883.0      # 這裡日期資料直接返回成浮點數了

 常見讀取excel不同資料型別的返回問題,如讀取日期格式的資料

一般使用sheet.cell(rowx,colx)方法獲取單元格資料,單元格資料型別判斷可以使用如下程式碼:

print(sheet.cell(1,2).ctype)
------------
# 返回日期資料的結果
3

注:ctype : 0 empty,1 string, 2 number, 3 date, 4 boolean, 5 error

讀取單元格日期資料為浮點數的處理方式:

程式碼如下:

import xlrd
from datetime import date
file = xlrd.open_workbook("excel_test.xlsx")
sheet = file.sheet_by_index(0) # 通過sheet索引獲取sheet物件
nrows_data = sheet.row_values(1)   # 獲取第二行資料,返回的是列表
ncols_data = sheet.col_values(0)   # 獲取第一列資料,返回的是列表
cell = sheet.cell(1,2)             # 獲取單元格資料,如第二行,第三列資料,返回的是浮點數
data_value = xlrd.xldate_as_tuple(sheet.cell_value(1,2) ,file.datemode)  # xldate_as_tuple()方法得到日期資料年月日時分秒的值並返回為元組
datatime2 = date(*data_value[:3]).strftime('%Y/%m/%d') # 擷取元組中的前三位,即年月日的值傳給data,並進行時間格式化

print(cell)
print(data_value)
print(datatime2)

-----------------------
# 返回結果
xldate:32883.0
(1990, 1, 10, 0, 0, 0)
1990/01/10

因此在讀取excel單元格資料,如遇到是日期格式的資料,可以加上如下程式碼判斷並處理:

if (sheet.cell(row,col).ctype == 3):
  date_value = xlrd.xldate_as_tuple(sheet.cell_value(row,col),file.datemode)
  date_tmp = date(*date_value[:3]).strftime('%Y/%m/%d')

三、xlwt向excel檔案寫入資料

 xlwt一般用於向excel檔案寫入資料,簡單示例如下:

import xlwt

workbook = xlwt.Workbook(encoding = 'utf-8')  # 建立工作簿
sheet = workbook.add_sheet('api_test')       # 新增一個sheet
data = sheet.write(0,0,'test')                # 向第一行第一列寫入資料:test
workbook.save('book.xlsx')                   # 儲存到book.xlsx中

 執行完成後會在該py檔案的同級目錄下生成一個book.xlsx的excel檔案,並新增了api_test的sheet表名,第一行第一列寫入資料:test

 向excel寫入資料時,可以設定單元格長寬、單元格合併、寫入時間格式資料以及新增超連結等

程式碼示例:

import xlwt
import datetime
workbook = xlwt.Workbook(encoding = 'utf-8')  # 建立工作簿
sheet = workbook.add_sheet('api_test')       # 新增一個sheet
data = sheet.write(4,0,'test')

sheet.col(0).width = 5000                      # 設定單元格寬度

style = xlwt.XFStyle()                         # 初始化表格樣式
style.num_format_str = 'M/D/YY'               # 設定時間格式,如:M/D/YY
sheet.write(5, 1, datetime.datetime.now(), style)      # 寫入時間格式資料

# 合併多列和和並多行
# 表示合併的行數是:按行索引,從0行到第0行,按列索引從0列到第3列,合併後並寫入資料:test1
sheet.write_merge(0, 0, 0, 3, 'test1')
# 表示合併的行數是:按行索引,從1行到第2行,按列索引從0列到第3列,合併後並寫入資料:test2
sheet.write_merge(1, 2, 0, 3, 'test2')

# 向單元格新增超連結
sheet.write(6, 0, xlwt.Formula('HYPERLINK("https://www.baidu.com/";"baidu")'))

workbook.save('book.xlsx')                   # 儲存到book.xlsx中

 執行後輸出excel效果如下:

四、xlutils操作excel檔案

 (1)拷貝excel表格

xlutils模組下的copy可以複製拷貝excel檔案,程式碼示例:

import xlrd
from xlutils.copy import copy
excel_file = xlrd.open_workbook("book.xlsx")
new_file = copy(excel_file)   # 拷貝檔案物件
new_file.save("book1.xlsx")   # 儲存為excel檔案

 執行以上程式碼會在同級目錄下生成一個book1.xlsx的excel檔案,該檔案和book.xlsx一樣,只是檔名稱不一樣而已,也就是複製excel檔案了

(2)修改excel檔案內容

除了copy為其他excel檔案外,也可以直接copy檔案修改後,儲存為同名的檔案,那修改的內容將直接覆蓋原excel檔案,達到修改的目的

示例:

import xlrd
from xlutils.copy import copy
excel_file = xlrd.open_workbook("book.xlsx")
new_file = copy(excel_file)
sheet = new_file.get_sheet(0) # 獲取表格的第一個sheet
sheet.write(0,1,"測試")      # 第一行第二列寫入:測試
sheet.write(1,1,"測試1")     # 第二行第二列寫入:測試1
new_file.save("book.xlsx")

 執行後book.xlsx表會修改更新

五、封裝操作excel讀和寫的類

通過上面介紹,基本具備使用xlrd、xlwt、xlutils模組進行excel檔案資料讀取和向excel檔案中寫入資料,在進行介面測試時,我們說到需要:測試資料和測試指令碼分離,後續的介面測試用例資料,我們統一寫入excel表格中,然後通過操作excel來讀取測試資料並將測試結果回填到excel中。因此,我們們需要對向excel讀取資料和向excel寫入資料的操作進行封裝。

我們操作上面的api測試用例這個sheet,封裝讀取excel資料的類,程式碼示例:

from xlrd import open_workbook
class Readexcel():

    def excel_data_list(self, filename, sheetname):
        '''
        :param filename: excel檔名稱
        :param sheetname: excel中表格sheet名稱
        :return: data_list
        '''
        data_list = []
        wb = open_workbook(filename)  # 開啟excel
        sh = wb.sheet_by_name(sheetname)  # 定位工作表
        header = sh.row_values(0)   # 獲取標題行的資料
        for i in range(1, sh.nrows):   # 跳過標題行,從第二行開始獲取資料
            col_datas = dict(zip(header, sh.row_values(i)))   # 將每一行的資料,組裝成字典
            data_list.append(col_datas)   # 將字典新增到列表中 ,列表巢狀字典,每個元素就是一個字典
        return data_list

if __name__ == '__main__':
    Readexcel()

 上面程式碼封裝了讀取excel資料的類,將每一行資料讀取出來組裝成字典並新增到列表中

例項化執行:

    data_list = Readexcel().excel_data_list('excel_test.xlsx','api測試用例')
    print(data_list)
----------------------- 
# 返回結果
[
 {'module': '視訊安防', 'url': 'http://imp-t.tfgreenroad.com:18092/console_api/recep/tv/list', 'id': 1.0, 'params': '{ "queryMsg":"","regionCode":"","devtypeCode":"","online":"","offset":"","limit":1,"type":""}', 'method': 'get', 'actual_res': '', 'data': '', 'expect_res': '', 'test_res': '', 'case_name': '分頁查詢視訊安防裝置列表', 'files': ''},
 {'module': '平臺管理', 'url': 'http://imp-t.tfgreenroad.com:18092/console_api/manage/appsys/info', 'id': 2.0, 'params': '', 'method': 'post', 'actual_res': '', 'data': '{"appName": "hahh","appId": "34434343","appUrl": "http://12306.com","appCode": "89","remark":""}', 'expect_res': '{"code": 200,"errMsg": ""}', 'test_res': '', 'case_name': '應用管理-單個應用系統新增', 'files': ''},
 {'module': '平臺管理', 'url': 'http://imp-t.tfgreenroad.com:18092/console_api/manage/appsys/info/upappid/89', 'id': 3.0, 'params': '', 'method': 'put', 'actual_res': '', 'data': '{"appId": "3232327676888"}', 'expect_res': '{"code": 200,"errMsg": ""}', 'test_res': '', 'case_name': '應用管理-修改應用appId', 'files': ''},
 {'module': '平臺管理', 'url': 'http://imp-t.tfgreenroad.com:18092/console_api/manage/devtype/list', 'id': 4.0, 'params': '{ "queryMsg":"15002","offset":"","limit":""}', 'method': 'get', 'actual_res': '', 'data': '', 'expect_res': '', 'test_res': '', 'case_name': '裝置分類-分頁獲取裝置型別', 'files': ''}
]

 封裝向excel寫入資料的類,程式碼示例:

from xlutils.copy import copy
from xlrd import open_workbook

class Write_excel():
    def write_result(self, filename, row, col1,col2,actual_res, test_res,sheet_name):
        '''
        :param filename: 檔名
        :param row: 要寫回的行
        :param col1: 要寫回的列
        :param col2: 要寫回的列
        :param actual_res: 實際結果
        :param test_res: 測試結果 :pass/failed
        :param sheet_name:指定的sheet表索引
        :return:
        '''
        old_workbook = open_workbook(filename)
        # 將已存在的excel拷貝進新的excel
        new_workbook = copy(old_workbook)
        # 獲取sheet
        new_worksheet = new_workbook.get_sheet(sheet_name)  # 第n個sheet,0表示第一個sheet
        # 寫入資料
        new_worksheet.write(row, col1, actual_res)
        new_worksheet.write(row, col2, test_res)
        # 儲存
        new_workbook.save("book.xlsx")

if __name__ == '__main__':
    Write_excel()

  這樣我們就完成了讀寫excel操作的封裝,後續介面測試資料的讀取和寫入就依靠這兩個類了。

 

相關文章