python_接口自動化測試框架
本文總結分享介紹接口測試框架開發,環境使用python3+selenium3+unittest+ddt+requests測試框架及ddt數據驅動,采用Excel管理測試用例等集成測試數據功能,以及使用HTMLTestRunner來生成測試報告,目前有開源的poman、Jmeter等接口測試工具,為什么還要開發接口測試框架呢?因接口測試工具也有存在幾點不足。
- 測試數據不可控制。比如接口返回數據不可控,就無法自動斷言接口返回的數據,不能斷定是接口程序引起,還是測試數據變化引起的錯誤,所以需要做一些初始化測試數據。接口工具沒有具備初始化測試數據功能,無法做到真正的接口測試自動化。
- 無法測試加密接口。實際項目中,多數接口不是可以隨便調用,一般情況無法摸擬和生成加密算法。如時間戳和MDB加密算法,一般接口工具無法摸擬。
- 擴展能力不足。開源的接口測試工具無法實現擴展功能。比如,我們想生成不同格式的測試報告,想將測試報告發送到指定郵箱,又想讓接口測試集成到CI中,做持續集成定時任務。
測試框架處理流程
測試框架處理過程如下:
- 首先初始化清空數據庫表的數據,向數據庫插入測試數據;
- 調用被測試系統提供的接口,先數據驅動讀取excel用例一行數據;
- 發送請求數據,根據傳參數據,向數據庫查詢得到對應的數據;
- 將查詢的結果組裝成JSON格式的數據,同時根據返回的數據值與Excel的值對比判斷,並寫入結果至指定Excel測試用例表格;
- 通過單元測試框架斷言接口返回的數據,並生成測試報告,最后把生成最新的測試報告HTML文件發送指定的郵箱。
測試框架結構目錄介紹
目錄結構介紹如下:
- config/: 文件路徑配置
- database/: 測試用例模板文件及數據庫和發送郵箱配置文件
- db_fixture/: 初始化接口測試數據
- lib/: 程序核心模塊。包含有excel解析讀寫、發送郵箱、發送請求、生成最新測試報告文件
- package/: 存放第三方庫包。如HTMLTestRunner,用於生成HTML格式測試報告
- report/: 生成接口自動化測試報告
- testcase/: 用於編寫接口自動化測試用例
- run_demo.py: 執行所有接口測試用例的主程序
- GitHub項目地址: https://github.com/yingoja/DemoAPI
數據庫封裝

1 [tester] 2 name = Jason 3 4 [mysqlconf] 5 host = 127.0.0.1 6 port = 3306 7 user = root 8 password = 123456 9 db_name = guest 10 11 [user] 12 # 發送郵箱服務器 13 HOST_SERVER = smtp.163.com 14 # 郵件發件人 15 FROM = 111@163.com 16 # 郵件收件人 17 TO = 222@126.com 18 # 發送郵箱用戶名/密碼 19 user = aaa 20 password = aaa 21 # 郵件主題 22 SUBJECT = 發布會系統接口自動化測試報告

1 #!/usr/bin/env python 2 # _*_ coding:utf-8 _*_ 3 __author__ = 'YinJia' 4 5 import os,sys 6 sys.path.append(os.path.dirname(os.path.dirname(__file__))) 7 from config import setting 8 from pymysql import connect,cursors 9 from pymysql.err import OperationalError 10 import configparser as cparser 11 12 # --------- 讀取config.ini配置文件 --------------- 13 cf = cparser.ConfigParser() 14 cf.read(setting.TEST_CONFIG,encoding='UTF-8') 15 host = cf.get("mysqlconf","host") 16 port = cf.get("mysqlconf","port") 17 user = cf.get("mysqlconf","user") 18 password = cf.get("mysqlconf","password") 19 db = cf.get("mysqlconf","db_name") 20 21 class DB: 22 """ 23 MySQL基本操作 24 """ 25 def __init__(self): 26 try: 27 # 連接數據庫 28 self.conn = connect(host = host, 29 user = user, 30 password = password, 31 db = db, 32 charset = 'utf8mb4', 33 cursorclass = cursors.DictCursor 34 ) 35 except OperationalError as e: 36 print("Mysql Error %d: %s" % (e.args[0],e.args[1])) 37 38 # 清除表數據 39 def clear(self,table_name): 40 real_sql = "delete from " + table_name + ";" 41 with self.conn.cursor() as cursor: 42 # 取消表的外鍵約束 43 cursor.execute("SET FOREIGN_KEY_CHECKS=0;") 44 cursor.execute(real_sql) 45 self.conn.commit() 46 47 # 插入表數據 48 def insert(self, table_name, table_data): 49 for key in table_data: 50 table_data[key] = "'"+str(table_data[key])+"'" 51 key = ','.join(table_data.keys()) 52 value = ','.join(table_data.values()) 53 real_sql = "INSERT INTO " + table_name + " (" + key + ") VALUES (" + value + ")" 54 55 with self.conn.cursor() as cursor: 56 cursor.execute(real_sql) 57 self.conn.commit() 58 59 # 關閉數據庫 60 def close(self): 61 self.conn.close() 62 63 # 初始化數據 64 def init_data(self, datas): 65 for table, data in datas.items(): 66 self.clear(table) 67 for d in data: 68 self.insert(table, d) 69 self.close()

1 #!/usr/bin/env python 2 # _*_ coding:utf-8 _*_ 3 __author__ = 'YinJia' 4 5 import sys, time, os 6 sys.path.append(os.path.dirname(os.path.dirname(__file__))) 7 from db_fixture.mysql_db import DB 8 9 # 定義過去時間 10 past_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()-100000)) 11 # 定義將來時間 12 future_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()+10000)) 13 14 # 創建測試數據 15 datas = { 16 # 發布會表數據 17 'sign_event':[ 18 {'id':1,'name':'紅米Pro發布會','`limit`':2000,'status':1,'address':'北京會展中心','start_time':future_time}, 19 {'id':2,'name':'蘋果iphon6發布會','`limit`':1000,'status':1,'address':'寶安體育館','start_time':future_time}, 20 {'id':3,'name':'華為榮耀8發布會','`limit`':2000,'status':0,'address':'深圳福田會展中心','start_time':future_time}, 21 {'id':4,'name':'蘋果iphon8發布會','`limit`':2000,'status':1,'address':'深圳灣體育中心','start_time':past_time}, 22 {'id':5,'name':'小米5發布會','`limit`':2000,'status':1,'address':'北京國家會議中心','start_time':future_time}, 23 ], 24 # 嘉賓表數據 25 'sign_guest':[ 26 {'id':1,'realname':'Tom','phone':13511886601,'email':'alen@mail.com','sign':0,'event_id':1}, 27 {'id':2,'realname':'Jason','phone':13511886602,'email':'sign@mail.com','sign':1,'event_id':1},