目录:导读
前言
接口自动化测试框架
环境使用python3+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:执行所有接口测试用例的主程序
数据库的封装
config.ini文件
[tester]
name = Jason
[mysqlconf]
host = 127.0.0.1
port = 3306
user = root
password = 123456
db_name = guest
[user]
# 发送邮箱服务器
HOST_SERVER = smtp.163.com
# 邮件发件人
FROM = 111@163.com
# 邮件收件人
TO = 222@126.com
# 发送邮箱用户名/密码
user = aaa
password = aaa
# 邮件主题
SUBJECT = 发布会系统接口自动化测试报告
mysql_db.py文件
import os,sys
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from config import setting
from pymysql import connect,cursors
from pymysql.err import OperationalError
import configparser as cparser
# --------- 读取config.ini配置文件 ---------------
cf = cparser.ConfigParser()
cf.read(setting.TEST_CONFIG,encoding='UTF-8')
host = cf.get("mysqlconf","host")
port = cf.get("mysqlconf","port")
user = cf.get("mysqlconf","user")
password = cf.get("mysqlconf","password")
db = cf.get("mysqlconf","db_name")
class DB:
"""
MySQL基本操作
"""
def __init__(self):
try:
# 连接数据库
self.conn = connect(host = host,
user = user,
password = password,
db = db,
charset = 'utf8mb4',
cursorclass = cursors.DictCursor
)
except OperationalError as e:
print("Mysql Error %d: %s" % (e.args[0],e.args[1]))
# 清除表数据
def clear(self,table_name):
real_sql = "delete from " + table_name + ";"
with self.conn.cursor() as cursor:
# 取消表的外键约束
cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
cursor.execute(real_sql)
self.conn.commit()
# 插入表数据
def insert(self, table_name, table_data):
for key in table_data:
table_data[key] = "'"+str(table_data[key])+"'"
key = ','.join(table_data.keys())
value = ','.join(table_data.values())
real_sql = "INSERT INTO " + table_name + " (" + key + ") VALUES (" + value + ")"
with self.conn.cursor() as cursor:
cursor.execute(real_sql)
self.conn.commit()
# 关闭数据库
def close(self):
self.conn.close()
# 初始化数据
def init_data(self, datas):
for table, data in datas.items():
self.clear(table)
for d in data:
self.insert(table, d)
self.close()
mysql_db.py文件
import sys, time, os
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from db_fixture.mysql_db import DB
# 定义过去时间
past_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()-100000))
# 定义将来时间
future_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time