Python接口自動化實戰(第二階段)- 數據與代碼分離
前面我們已經實現了用unittest框架編寫測試用例,實現了請求接口的封裝,這樣雖然已經可以完成接口的自動化測試,但是其復用性並不高。
我們看到每個方法(測試用例)的代碼幾乎是一模一樣的,試想一下,在我們的測試場景中,一個註冊接口有可能會有十幾條到幾十條測試用例,如果每組數據都編寫一個方法,這樣將會有更多的重復項代碼,不僅執行效率不高,也不好維護。
接下來將會對框架進行優化,采用數據驅動方式,1)把測試數據用excel表格管理起來,代碼做封裝,2)用ddt來驅動測試,兩部分相互獨立。
1.數據與代碼分離:excel管理測試數據
在上一節的代碼中, test_register.py 模塊中,定義了三個方法(三個測試用例),每一個測試用例都需要提供一組測試數據:url,params,method,expect_res等,不利於修改和構建,現在我們新建 excel文件(TestData.xlsx )。如下:
自動化用例設計:
關於自動化測試用例的設計,是基於對接口業務流程的熟悉,只有熟悉業務流程,才能設計出較好的自動化測試數據。這邊要考慮的點很多,
- id:用例編號,從1開始,唯一
- module:接口模塊
- case_name:用例名稱
- method:請求類型
- url:接口地址信息
- params:請求參數
用例設計好了,這邊我遇到了三個問題:
第一:如何讀取測試數據?
第二:讀取的測試數據,應該存儲成什麽格式?
第三:數據如何傳遞?
當然,用例的設計對於越復雜的場景,考慮的就會越多,其中有一點很重要,盡量保持用例的獨立性,用例之間的關聯性不要太強,避免一條用例的失敗,導致其他用例也無法執行。
xlrd 使用
安裝xlrd第三方庫,pip install xlrd.from xlrd import open_workbook
wb = open_workbook("TestData.xlsx") # 打開excel sh = wb.sheet_by_name("register") # 定位工作表 print(sh.row_values(0)) # 輸出第1行的所有值(列表格式) print(dict(zip(sh.row_values(0),sh.row_values(1)))) # 將數據和標題組成字
for i in range(sh.nrows):print(sh.row_values(i))
封裝讀取excel操作 -如何讀取測試數據?
實現代碼如下:
from xlrd import open_workbook class Doexcel(): def excel_data_list(self, filename, sheetname): 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(sh.row_values(0), sh.row_values(i))) # 將標題和每一行的數據,組裝成字典 data_list.append(col_datas) # 將字典添加到列表中 ,列表嵌套字典,相當於每個字典的元素都是一個列表(也就是一行數據) return data_list def get_test_data(self, data_list, case_id): ‘‘‘ :param data_list: 工作表的所有行數據 :param case_id: 用例id,用來判斷執行哪幾條case。如果id=all ,那就執行所有用例;否則,執行列表參數中指定的用例 :return: 返回最終要執行的測試用例 ‘‘‘ if case_id == ‘all‘: final_data = data_list else: final_data = [] for item in data_list: if item[‘id‘] in case_id: final_data.append(item) return final_data
if __name__ == ‘__main__‘:
data_list=Doexcel().excel_data_list(‘F:\JialiProgramfile\serviceX_API_Test\Test_datas\TestData.xlsx‘,‘register‘)
final_data=Doexcel().get_test_data(data_list, [1,2,3])
print(final_data)
執行結果
[{‘method‘: ‘post‘, ‘expect_res‘: 200.0, ‘actual_res‘: ‘‘, ‘id‘: 1.0, ‘test_res‘: ‘‘, ‘case_name‘: ‘test_register_normal‘, ‘url‘: ‘http://27.154.55.14:8180/api/fcb2bcrm/webRegister‘, ‘module‘: ‘register‘, ‘params‘: ‘{"LoginAccount":"[email protected]","Password":"123456","Type":"Pro"}‘},
{‘method‘: ‘post‘, ‘expect_res‘: 400.0, ‘actual_res‘: ‘‘, ‘id‘: 2.0, ‘test_res‘: ‘‘, ‘case_name‘: ‘test_register_existing‘, ‘url‘: ‘http://27.154.55.14:8180/api/fcb2bcrm/webRegister‘, ‘module‘: ‘register‘, ‘params‘: ‘{"LoginAccount":"[email protected]","Password":"123456","Type":"Pro"}‘},
{‘method‘: ‘post‘, ‘expect_res‘: 400.0, ‘actual_res‘: ‘‘, ‘id‘: 3.0, ‘test_res‘: ‘‘, ‘case_name‘: ‘test_register_invalid_email‘, ‘url‘: ‘http://27.154.55.14:8180/api/fcb2bcrm/webRegister‘, ‘module‘: ‘register‘, ‘params‘: ‘{"LoginAccount":"test01@gamil","Password":"123456","Type":"Pro"}‘}]
2.ddt 數據驅動- 如果傳遞數據?
數據驅動,個人理解就是測試數據的參數化
1)安裝第三方庫 : pip install ddt
2)引入ddt模塊:from ddt import ddt,data
3)test_register.py 代碼加入ddt
# 導入 import unittest import requests from Common.http_request import HttpRequest from ddt import ddt,data # 引入ddt模塊 from Common.do_excel import * test_data = Doexcel().excel_data_list(‘F:\JialiProgramfile\serviceX_API_Test\Test_datas\TestData.xlsx‘,‘register‘) #讀取工作表 register 的所有數據 ,返回的是個列表嵌套字典格式 @ddt class TestRegister (unittest.TestCase): # 類必須以Test開頭,繼承TestCase def setUp(self): print("======開始執行測試用例======") def tearDown(self): print("======測試用例執行完畢======") # 測試用例 @data(*test_data) def test_register(self, data_itme): # data_item 就是每一組測試數據(字典的形式) # 發送請求 res = HttpRequest().http_request(data_itme[‘url‘],eval(data_itme[‘params‘]),data_itme[‘method‘]) # 斷言: try: self.assertEqual(int(data_itme[‘expect_res‘]), res.status_code) except AssertionError as e: print(‘Failed‘) raise e # 註意一定要拋出異常
3.測試結果寫回 - 擴展doExcel類
在excel表格中,有 兩列的值是需要在執行完測試用例後寫回的:實際結果和測試結果。
def write_back_result(self, filename, sheetname, row, actual_res, test_result): ‘‘‘ :param filename: 文件名 :param sheetname: 要寫回數據的表格 :param row: 要寫回的行數 :param actual_res: 實際結果 :實際結果是第8列,測試結果是第9列 ,比如:(2,8)(2,9) :param test_result: 測試結果 :pass/failed :return: ‘‘‘ wb = load_workbook(filename) sheet = wb[sheetname] sheet.cell(row,8).value = actual_res sheet.cell(row,9).value = test_result wb.save(filename)
在test_register.py文件中,每次執行完一組測試數據,調用 write_back_result()方法,將所需要的參數傳遞進去。
Python接口自動化實戰(第二階段)- 數據與代碼分離