工程技术研究中心网站建设要求,手机网站建设哪家好,大气网站源码下载,从哪看出网站的建站公司这篇文章主要介绍了Pythonrequestunittest实现接口测试框架集成实例#xff0c;小编觉得挺不错的#xff0c;现在分享给大家#xff0c;也给大家做个参考。一起跟随小编过来看看吧
1、为什么要写代码实现接口自动化
大家知道很多接口测试工具可以实现对接口的测试#xf…这篇文章主要介绍了Pythonrequestunittest实现接口测试框架集成实例小编觉得挺不错的现在分享给大家也给大家做个参考。一起跟随小编过来看看吧
1、为什么要写代码实现接口自动化
大家知道很多接口测试工具可以实现对接口的测试如postman、jmeter、fiddler等等而且使用方便那么为什么还要写代码实现接口自动化呢工具虽然方便但也不足之处
测试数据不可控制
接口测试本质是对数据的测试调用接口输入一些数据随后接口返回一些数据。验证接口返回数据的正确性。在用工具运行测试用例之前不得不手动向数据库中插入测试数据。这样我们的接口测试是不是就没有那么“自动化了”。
无法测试加密接口
这是接口测试工具的一大硬伤如我们前面开发的接口用工具测试完全没有问题但遇到需要对接口参 数进行加密/解密的接口例如 md5、base64、AES 等常见加密方式。本书第十一章会对加密接口进行介绍。 又或者接口的参数需要使用时间戳也是工具很难模拟的。
扩展能力不足
当我们在享受工具所带来的便利的同时往往也会受制于工具所带来的局限。例如我想将测试结果生 成 HMTL 格式测试报告我想将测试报告发送到指定邮箱。我想对接口测试做定时任务。我想对接口测试做持续集成。这些需求都是工具难以实现的。
2、接口自动化测试设计
接口测试调用过程可以用下图概括增加了测试数据库 一般的 接口工具 测试过程
1、接口工具调用被测系统的接口传参 usernamezhangsan。
2、系统接口根据传参usernamezhangsan向 正式数据库 中查询数据。
3、将查询结果组装成一定格式的数据并返回给被调用者。
4、人工或通过工具的断言功能检查接口测试的正确性。
接口自动化测试项目为了使接口测试对数据变得可控测试过程如下
1、接口测试项目先向 测试数据库 中插入测试数据zhangsan 的个人信息。
2、调用被测系统接口传参 usernamezhangsan。
3、系统接口根据传参usernamezhangsan向测试数据库中进行查询并得到 zhangsan 个人信息。
4、将查询结果组装成一定格式的数据并返回给被调用者。
5、通过单元测试框架断言接口返回的数据zhangsan 的个人信息并生成测试报告。
为了使正式数据库的数据不被污染建议使用独立的 测试数据库 。
3、requests库
Requests 使用的是 urllib3因此继承了它的所有特性。Requests 支持 HTTP 连接保持和连接池 支持 使用cookie保持会话 支持 文件上传 支持 自动确定响应内容的编码。 对request库的更详细的介绍可以看我之前接口测试基础的文章
4、接口测试代码示例
下面以之前用 pythondjango 开发的用户签到系统为背景展示接口测试的代码。
为什么开发接口开发的接口主要给谁来用
前端和后端分离是近年来 Web 应用开发的一个发展趋势。这种模式将带来以下优势
1、后端可以不用必须精通前端技术HTML/JavaScript/CSS只专注于数据的处理对外提供 API 接口。
2、前端的专业性越来越高通过 API 接口获取数据从而专注于页面的设计。
3、前后端分离增加接口的应用范围开发的接口可以应用到 Web 页面上也可以应用到移动 APP 上。
在这种开发模式下接口测试工作就会变得尤为重要了。
开发实现的接口代码示例
# 添加发布会接口实现
def add_event(request):eid request.POST.get(eid,) # 发布会idname request.POST.get(name,) # 发布会标题limit request.POST.get(limit,) # 限制人数status request.POST.get(status,) # 状态address request.POST.get(address,) # 地址start_time request.POST.get(start_time,) # 发布会时间if eid or name or limit or address or start_time :return JsonResponse({status:10021,message:parameter error})result Event.objects.filter(ideid)if result:return JsonResponse({status:10022,message:event id already exists})result Event.objects.filter(namename)if result:return JsonResponse({status:10023,message:event name already exists})if status :status 1try:Event.objects.create(ideid,namename,limitlimit,addressaddress,statusint(status),start_timestart_time)except ValidationError:error start_time format error. It must be in YYYY-MM-DD HH:MM:SS format.return JsonResponse({status:10024,message:error})return JsonResponse({status:200,message:add event success})
通过POST请求接收发布会参数发布会id、标题、人数、状态、地址和时间等参数。
首先判断eid、name、limit、address、start_time等字段均不能为空否则JsonResponse()返回相应的状态码和提示。JsonResponse()是一个非常有用的方法它可以直接将字典转化成Json格式返回到客户端。
接下来判断发布会id是否存在以及发布会名称name是否存在如果存在将返回相应的状态码和 提示信息。
再接下来判断发布会状态是否为空如果为空将状态设置为1True。
最后将数据插入到 Event 表在插入的过程中如果日期格式错误将抛出 ValidationError 异常接收 该异常并返回相应的状态和提示否则插入成功返回状态码200和“add event success”的提示。
# 发布会查询接口实现
def get_event_list(request):eid request.GET.get(eid, ) # 发布会idname request.GET.get(name, ) # 发布会名称if eid and name :return JsonResponse({status:10021,message:parameter error})if eid ! :event {}try:result Event.objects.get(ideid)except ObjectDoesNotExist:return JsonResponse({status:10022, message:query result is empty})else:event[eid] result.idevent[name] result.nameevent[limit] result.limitevent[status] result.statusevent[address] result.addressevent[start_time] result.start_timereturn JsonResponse({status:200, message:success, data:event})if name ! :datas []results Event.objects.filter(name__containsname)if results:for r in results:event {}event[eid] r.idevent[name] r.nameevent[limit] r.limitevent[status] r.statusevent[address] r.addressevent[start_time] r.start_timedatas.append(event)return JsonResponse({status:200, message:success, data:datas})else:return JsonResponse({status:10022, message:query result is empty})
通过GET请求接收发布会id和name 参数。两个参数都是可选的。首先判断当两个参数同时为空接口返回状态码10021参数错误。
如果发布会id不为空优先通过id查询因为id的唯一性所以查询结果只会有一条将查询结果 以 key:value 对的方式存放到定义的event字典中并将数据字典作为整个返回字典中data对应的值返回。
name查询为模糊查询查询数据可能会有多条返回的数据稍显复杂首先将查询的每一条数据放到一 个字典event中再把每一个字典再放到数组datas中最后再将整个数组做为返回字典中data对应的值返回。
接口测试代码示例
#查询发布会接口测试代码
import requestsurl http://127.0.0.1:8000/api/get_event_list/
r requests.get(url, params{eid:1})
result r.json()
print(result)
assert result[status] 200
assert result[message] success
assert result[data][name] xx 产品发布会
assert result[data][address] 北京林匹克公园水立方
assert result[data][start_time] 2016-10-15T18:00:00
因为“发布会查询接口”是GET类型所以通过requests库的get()方法调用第一个参数为调用接口的URL地址params设置接口的参数参数以字典形式组织。
json()方法可以将接口返回的json格式的数据转化为字典。
接下来就是通过 assert 语句对接字典中的数据进行断言。分别断言status、message 和data的相关数据等。
使用unittest单元测试框架开发接口测试用例
#发布会查询接口测试代码
import unittest
import requestsclass GetEventListTest(unittest.TestCase):def setUp(self):self.base_url http://127.0.0.1:8000/api/get_event_list/def test_get_event_list_eid_null(self): eid 参数为空 r requests.get(self.base_url, params{eid:})result r.json()self.assertEqual(result[status], 10021)self.assertEqual(result[message], parameter error)def test_get_event_list_eid_error(self): eid901 查询结果为空 r requests.get(self.base_url, params{eid:901})result r.json()self.assertEqual(result[status], 10022)self.assertEqual(result[message], query result is empty)def test_get_event_list_eid_success(self): 根据 eid 查询结果成功 r requests.get(self.base_url, params{eid:1})result r.json()self.assertEqual(result[status], 200)self.assertEqual(result[message], success)self.assertEqual(result[data][name],umx6发布会)self.assertEqual(result[data][address],u北京国家会议中心)def test_get_event_list_nam_result_null(self): 关键字‘abc查询 r requests.get(self.base_url, params{name:abc})result r.json()self.assertEqual(result[status], 10022)self.assertEqual(result[message], query result is empty)def test_get_event_list_name_find(self): 关键字‘发布会模糊查询 r requests.get(self.base_url, params{name:发布会})result r.json()self.assertEqual(result[status], 200)self.assertEqual(result[message], success)self.assertEqual(result[data][0][name],umx6发布会)self.assertEqual(result[data][0][address],u北京国家会议中心)
49if __name__ __main__:unittest.main()
unittest单元测试框架可以帮助 组织和运行接口测试用例。
5、接口自动化测试框架实现
关于接口自动化测试unittest 已经帮我们做了大部分工作接下来只需要 集成数据库操作 以及 HTMLTestRunner测试报告生成 扩展即可。
框架结构如下图 pyrequests 框架
db_fixture/ 初始化接口测试数据。
interface/ 用于编写接口自动化测试用例。
report/ 生成接口自动化测试报告。
db_config.ini 数据库配置文件。
HTMLTestRunner.py unittest 单元测试框架扩展生成 HTML 格式的测试报告。
run_tests.py 执行所有接口测试用例。
4.1、数据库配置
首先需要修改被测系统将数据库指向测试数据库。以 MySQL数据库为例针对 django 项目而言修改.../guest/settings.py 文件。可以在系统测试环境单独创建一个测试库。 这样做的目的是让接口测试的数据不会清空或污染到功能测试库的数据。 其他框架开发的项目与django项目类似这个工作一般由开发同学完成我们测试同学更多关注的是测试框架的代码。
4.2、框架代码实现
4.2.1、首先创 建数据库配置文件.../db_config.ini 4.2.2、接下来 简单封装数据库操作数据库表数据的插入和清除 .../db_fixture/ mysql_db.py
import pymysql.cursors
import os
import configparser as cparser# Reading db_config.ini setting
base_dir str(os.path.dirname(os.path.dirname(__file__)))
base_dir base_dir.replace(\\, /)
file_path base_dir /db_config.inicf cparser.ConfigParser()cf.read(file_path)
host cf.get(mysqlconf, host)
port cf.get(mysqlconf, port)
db cf.get(mysqlconf, db_name)
user cf.get(mysqlconf, user)
password cf.get(mysqlconf, password)# MySql base operating
class DB:def __init__(self):try:# Connect to the databaseself.connection pymysql.connect(hosthost,portint(port),useruser,passwordpassword,dbdb,charsetutf8mb4,cursorclasspymysql.cursors.DictCursor)except pymysql.err.OperationalError as e:print(Mysql Error %d: %s % (e.args[0], e.args[1]))# clear table datadef clear(self, table_name):# real_sql truncate table table_name ;real_sql delete from table_name ;with self.connection.cursor() as cursor:cursor.execute(SET FOREIGN_KEY_CHECKS0;)cursor.execute(real_sql)self.connection.commit()# insert sql statementdef 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 )#print(real_sql)with self.connection.cursor() as cursor:cursor.execute(real_sql)self.connection.commit()# close databasedef close(self):self.connection.close()# init datadef init_data(self, datas):for table, data in datas.items():self.clear(table)for d in data:self.insert(table, d)self.close()if __name__ __main__:db DB()table_name sign_eventdata {id:1,name:红米,limit:2000,status:1,address:北京会展中心,start_time:2016-08-20 00:25:42}table_name2 sign_guestdata2 {realname:alen,phone:12312341234,email:alenmail.com,sign:0,event_id:1}db.clear(table_name)db.insert(table_name, data)db.close()
首先读取 db_config.ini 配置文件。 创建 DB 类__init__()方法初始化通过 pymysql.connect()连接数据库。
因为这里只用到数据库表的清除和插入所以只创建 clear()和 insert()两个方法。其中insert()方法对数 据的插入做了简单的格式转化可将字典转化成 SQL 插入语句这样格式转化了方便了数据库表数据的创建。
最后通过 close()方法用于关闭数据库连接。
4.2.3、接下来接下来 创建测试数据 .../db_fixture/ test_data.py
import sys
sys.path.append(../db_fixture)
try:from mysql_db import DB
except ImportError:from .mysql_db import DB# create data
datas {sign_event:[{id:1,name:红米Pro发布会,limit:2000,status:1,address:北京会展中心,start_time:2017-08-20 14:00:00},{id:2,name:可参加人数为0,limit:0,status:1,address:北京会展中心,start_time:2017-08-20 14:00:00},{id:3,name:当前状态为0关闭,limit:2000,status:0,address:北京会展中心,start_time:2017-08-20 14:00:00},{id:4,name:发布会已结束,limit:2000,status:1,address:北京会展中心,start_time:2001-08-20 14:00:00},{id:5,name:小米5发布会,limit:2000,status:1,address:北京国家会议中心,start_time:2017-08-20 14:00:00},],sign_guest:[{id:1,realname:alen,phone:13511001100,email:alenmail.com,sign:0,event_id:1},{id:2,realname:has sign,phone:13511001101,email:signmail.com,sign:1,event_id:1},{id:3,realname:tom,phone:13511001102,email:tommail.com,sign:0,event_id:5},],
}# Inster table datas
def init_data():DB().init_data(datas)if __name__ __main__:init_data()
init_data()函数用于读取 datas 字典中的数据调用 DB 类中的 clear()方法清除数据库然后调用 insert() 方法插入表数据。
4.2.4、编写 接口测试用例 。创建添加发布会接口测试文件.../interface/ add_event_test.py
import unittest
import requests
import os, sys
parentdir os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, parentdir)
from db_fixture import test_dataclass AddEventTest(unittest.TestCase): 添加发布会 def setUp(self):self.base_url http://127.0.0.1:8000/api/add_event/def tearDown(self):print(self.result)def test_add_event_all_null(self): 所有参数为空 payload {eid:,:,limit:,address:,start_time:}r requests.post(self.base_url, datapayload)self.result r.json()self.assertEqual(self.result[status], 10021)self.assertEqual(self.result[message], parameter error)def test_add_event_eid_exist(self): id已经存在 payload {eid:1,name:一加4发布会,limit:2000,address:深圳宝体,start_time:2017}r requests.post(self.base_url, datapayload)self.result r.json()self.assertEqual(self.result[status], 10022)self.assertEqual(self.result[message], event id already exists)def test_add_event_name_exist(self): 名称已经存在 payload {eid:11,name:红米Pro发布会,limit:2000,address:深圳宝体,start_time:2017}r requests.post(self.base_url,datapayload)self.result r.json()self.assertEqual(self.result[status], 10023)self.assertEqual(self.result[message], event name already exists)def test_add_event_data_type_error(self): 日期格式错误 payload {eid:11,name:一加4手机发布会,limit:2000,address:深圳宝体,start_time:2017}r requests.post(self.base_url,datapayload)self.result r.json()self.assertEqual(self.result[status], 10024)self.assertIn(start_time format error., self.result[message])def test_add_event_success(self): 添加成功 payload {eid:11,name:一加4手机发布会,limit:2000,address:深圳宝体,start_time:2017-05-10 12:00:00}r requests.post(self.base_url,datapayload)self.result r.json()self.assertEqual(self.result[status], 200)self.assertEqual(self.result[message], add event success)if __name__ __main__:test_data.init_data() # 初始化接口测试数据unittest.main()
在测试接口之前调用test_data.py文件中的init_data()方法初始化数据库中的测试数据。
创建AddEventTest测试类继承 unittest.TestCase 类通过创建测试用例调用相关接口并验证接口返回 的数据。
4.2.5、创建 run_tests.py 文件
当开发的接口达到一定数量后就需要考虑 分文件分目录 的来 划分 接口测试用例如何批量的执行不同文件目录下的用例呢unittest单元测试框架提供的 discover() 方法可以帮助我们做到这一点。并使用 HTMLTestRunner 扩展生成 HTML 格式的测试报告。
import time, sys
sys.path.append(./interface)
sys.path.append(./db_fixture)
from HTMLTestRunner import HTMLTestRunner
import unittest
from db_fixture import test_data# 指定测试用例为当前文件夹下的 interface 目录
test_dir ./interface
discover unittest.defaultTestLoader.discover(test_dir, pattern*_test.py)if __name__ __main__:test_data.init_data() # 初始化接口测试数据now time.strftime(%Y-%m-%d %H_%M_%S)filename ./report/ now _result.htmlfp open(filename, wb)runner HTMLTestRunner(streamfp,titleGuest Manage System Interface Test Report,descriptionImplementation Example with: )runner.run(discover)fp.close()
首先通过调用test_data.py文件中的init_data()函数来初始化接口测试数据。
使用unittest框架所提供的discover()方法查找 interface/ 目录下所有匹配_test.py 的测试文件星 号匹配任意字符。
HTMLTestRunner 为unittest单元测试框架的扩展利用它所提供的HTMLTestRunner()类来替换unittest单元测试框架的TextTestRunner()类从而生成HTML格式的测试报告。
遗憾的是HTMLTestRunner并不支持Python3.x大家可以在网上找到适用于Python3.x的HTMLTestRunner.py文件使用在自己的接口自动化工程中。
通过 time 的 strftime()方法获取当前时间并且转化成一定的时间格式。作为测试报告的名称。这样做目的是是为了避免因为生成的报告的名称重名而造成报告的覆盖。最终将测试报告存放于report/目录下面。如下图一张完整的接口自动化测试报告。 以上就是本文的全部内容希望对大家的学习有所帮助也希望大家多多支持“软件测试pytest”。
最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走 软件测试面试小程序
被百万人刷爆的软件测试题库谁用谁知道全网最全面试刷题小程序手机就可以刷题地铁上公交上卷起来
涵盖以下这些面试题板块 1、软件测试基础理论 2、web,app接口功能测试 3、网络 4、数据库 5、linux 6、web,app接口自动化 7、性能测试 8、编程基础9、hr面试题 10、开放性测试题11、安全测试12、计算机基础 这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴上万个测试工程师们走过最艰难的路程希望也能帮助到你