基于python+unittest实现接口自动化测试

简介

本文通过从Postman获取基本的接口测试Code简单的接口测试入手,一步步调整优化接口调用,以及增加基本的结果判断,讲解Python自带的Unittest框架调用,期望各位可以通过本文对接口自动化测试有一个大致的了解。

为什么要做接口自动化测试?

在当前互联网产品迭代频繁的背景下,回归测试的时间越来越少,很难在每个迭代都对所有功能做完整回归。但接口自动化测试因其实现简单、维护成本低,容易提高覆盖率等特点,越来越受重视。

为什么要自己写框架呢?

使用Postman调试通过过直接可以获取接口测试的基本代码,结合使用requets + unittest很容易实现接口自动化测试的封装,而且requests的api已经非常人性化,非常简单,但通过封装以后(特别是针对公司内特定接口),可以进一步提高脚本编写效率。

同时,在这我准备了一份软件测试视频教程(含接口、自动化、性能等),需要的可以直接在下方观看,或者直接关注VX公众号:互联网杂货铺这份测试文档资料也打包在里面啦,免费领取!

软件测试视频教程观看处:

【B站最系统自动化测试教程】整整400集,从入门到项目实战,只需18天,手把手带你进阶自动化测试!!!

一个现有的简单接口例子

下面使用requests + unittest测试一个查询接口

接口信息如下

请求信息:

Method:POST

URL:api/match/image/getjson

Request:

{
"category": "image",
"offset": "0",
"limit": "30",
"sourceId": "0",
"metaTitle": "",
"metaId": "0",
"classify": "unclassify",
"startTime": "",
"endTime": "",
"createStart": "",
"createEnd": "",
"sourceType": "",
"isTracking": "true",
"metaGroup": "",
"companyId": "0",
"lastDays": "1",
"author": ""
}

 Response示例:

{
"timestamp" : xxx,
"errorMsg" : "",
"data" : {
"config" : xxx
}

Postman测试方法

测试思路

1.获取Postman原始脚本

2.使用requests库模拟发送HTTP请求**

3.对原始脚本进行基础改造**

4.使用python标准库里unittest写测试case**

原始脚本实现

未优化

该代码只是简单的一次调用,而且返回的结果太多,很多返回信息暂时没用,示例代码如下:

import requests
 
url = "http://cpright.xinhua-news.cn/api/match/image/getjson"
 
querystring = {"category":"image","offset":"0","limit":"30","sourceId":"0","metaTitle":"","metaId":"0","classify":"unclassify","startTime":"","endTime":"","createStart":"","createEnd":"","sourceType":"","isTracking":"true","metaGroup":"","companyId":"0","lastDays":"1","author":""}
 
headers = {
    'cache-control': "no-cache",
    'postman-token': "e97a99b0-424b-b2a5-7602-22cd50223c15"
    }
 
response = requests.request("POST", url, headers=headers, params=querystring)
 
print(response.text)

优化 第一版

调整代码结构,输出结果Json出来,获取需要验证的response.status_code,以及获取结果校验需要用到的results['total']

#!/usr/bin/env python
#coding: utf-8
'''
unittest merchant backgroud interface
@author: zhang_jin
@version: 1.0
@see:http://www.python-requests.org/en/master/
'''
 
import unittest
import json
import traceback
import requests
 
 
url = "http://cpright.xinhua-news.cn/api/match/image/getjson"
 
querystring = {
    "category": "image",
    "offset": "0",
    "limit": "30",
    "sourceId": "0",
    "metaTitle": "",
    "metaId": "0",
    "classify": "unclassify",
    "startTime": "",
    "endTime": "",
    "createStart": "",
    "createEnd": "",
    "sourceType": "",
    "isTracking": "true",
    "metaGroup": "",
    "companyId": "0",
    "lastDays": "1",
    "author": ""
}
 
headers = {
    'cache-control': "no-cache",
    'postman-token': "e97a99b0-424b-b2a5-7602-22cd50223c15"
    }
 
#Post接口调用
response = requests.request("POST", url, headers=headers, params=querystring)
 
#对返回结果进行转义成json串
results = json.loads(response.text)
 
#获取http请求的status_code
print "Http code:",response.status_code
 
#获取结果中的total的值
print results['total']
#print(response.text)

优化 第二版

接口调用异常处理,增加try,except处理,对于返回response.status_code,返回200进行结果比对,不是200数据异常信息。

#!/usr/bin/env python
#coding: utf-8
'''
unittest merchant backgroud interface
@author: zhang_jin
@version: 1.0
@see:http://www.python-requests.org/en/master/
'''
 
import json
import traceback
import requests
 
 
url = "http://cpright.xinhua-news.cn/api/match/image/getjson"
 
querystring = {
    "category": "image",
    "offset": "0",
    "limit": "30",
    "sourceId": "0",
    "metaTitle": "",
    "metaId": "0",
    "classify": "unclassify",
    "startTime": "",
    "endTime": "",
    "createStart": "",
    "createEnd": "",
    "sourceType": "",
    "isTracking": "true",
    "metaGroup": "",
    "companyId": "0",
    "lastDays": "1",
    "author": ""
}
 
headers = {
    'cache-control': "no-cache",
    'postman-token': "e97a99b0-424b-b2a5-7602-22cd50223c15"
    }
 
 
try:
    #Post接口调用
    response = requests.request("POST", url, headers=headers, params=querystring)
 
    #对http返回值进行判断,对于200做基本校验
    if response.status_code == 200:
        results = json.loads(response.text)
        if results['total'] == 191:
            print "Success"
        else:
            print "Fail"
            print results['total']
    else:
        #对于http返回非200的code,输出相应的code
        raise Exception("http error info:%s" %response.status_code)
except:
    traceback.print_exc()

优化 第三版

1.该版本改动较大,引入config文件,单独封装结果校验模块,引入unittest模块,实现接口自动调用,并增加log处理模块;
2.对不同Post请求结果进行封装,不同接口分开调用;
3.测试用例的结果进行统计并最终输出

#!/usr/bin/env python
#coding: utf-8
'''
unittest interface
@author: zhang_jin
@version: 1.0
@see:http://www.python-requests.org/en/master/
'''
 
import unittest
import json
import traceback
import requests
import time
import result_statistics
import config as cf
from com_logger import  match_Logger
 
 
class MyTestSuite(unittest.TestCase):
    """docstring for MyTestSuite"""
    #@classmethod
    def sedUp(self):
        print "start..."
    #图片匹配统计
    def test_image_match_001(self):
        url = cf.URL1
 
        querystring = {
            "category": "image",
            "offset": "0",
            "limit": "30",
          "sourceId": "0",
          "metaTitle": "",
          "metaId": "0",
          "classify": "unclassify",
          "startTime": "",
          "endTime": "",
          "createStart": "",
          "createEnd": "",
          "sourceType": "",
          "isTracking": "true",
          "metaGroup": "",
          "companyId": "0",
          "lastDays": "1",
          "author": ""
        }
        headers = {
            'cache-control': "no-cache",
            'postman-token': "545a2e40-b120-2096-960c-54875be347be"
            }
 
 
        response = requests.request("POST", url, headers=headers, params=querystring)
        if response.status_code == 200:
            response.encoding = response.apparent_encoding
            results = json.loads(response.text)
            #预期结果与实际结果校验,调用result_statistics模块
            result_statistics.test_result(results,196)
        else:
            print "http error info:%s" %response.status_code
 
        #match_Logger.info("start image_query22222")
        #self.assertEqual(results['total'], 888)
 
        '''
        try:
            self.assertEqual(results['total'], 888)
        except:
            match_Logger.error(traceback.format_exc())
        #print results['total']
        '''
 
    #文字匹配数据统计
    def test_text_match_001(self):
 
        text_url = cf.URL2
 
        querystring = {
            "category": "text",
            "offset": "0",
            "limit": "30",
            "sourceId": "0",
            "metaTitle": "",
            "metaId": "0",
            "startTime": "2017-04-14",
            "endTime": "2017-04-15",
            "createStart": "",
            "createEnd": "",
            "sourceType": "",
            "isTracking": "true",
            "metaGroup": "",
            "companyId": "0",
            "lastDays": "0",
            "author": "",
            "content": ""
        }
        headers = {
            'cache-control': "no-cache",
            'postman-token': "ef3c29d8-1c88-062a-76d9-f2fbebf2536c"
            }
 
        response = requests.request("POST", text_url, headers=headers, params=querystring)
 
        if response.status_code == 200:
            response.encoding = response.apparent_encoding
            results = json.loads(response.text)
            #预期结果与实际结果校验,调用result_statistics模块
            result_statistics.test_result(results,190)
        else:
            print "http error info:%s" %response.status_code
 
        #print(response.text)
 
    def tearDown(self): 
        pass
 
if __name__ == '__main__':
    #image_match_Logger = ALogger('image_match', log_level='INFO')
 
    #构造测试集合
    suite=unittest.TestSuite()
    suite.addTest(MyTestSuite("test_image_match_001"))
    suite.addTest(MyTestSuite("test_text_match_001"))
 
    #执行测试
    runner = unittest.TextTestRunner()
    runner.run(suite)
    print "success case:",result_statistics.num_success
    print "fail case:",result_statistics.num_fail
    #unittest.main()

最终输出日志信息

Zj-Mac:unittest lazybone$ python image_test_3.py 
测试结果:通过
 
.测试结果:不通过 
错误信息: 期望返回值:190 实际返回值:4522
 
.
----------------------------------------------------------------------
Ran 2 tests in 0.889s
 
OK
success case: 1
fail case: 1

后续改进建议

1.unittest输出报告也可以推荐使用HTMLTestRunner(我目前是对结果统计进行了封装)

2.接口的继续封装,参数化,模块化

3.unittest单元测试框架实现参数化调用第三方模块引用(nose-parameterized)

4.持续集成运行环境、定时任务、触发运行、邮件发送等一系列功能均可以在Jenkins上实现。

PS:这里分享一套软件测试的自学教程合集。对于在测试行业发展的小伙伴们来说应该会很有帮助。除了基础入门的资源,博主也收集不少进阶自动化的资源,从理论到实战,知行合一才能真正的掌握。全套内容已经打包到网盘,内容总量接近500个G。如需要软件测试学习资料,关注公众号(互联网杂货铺),后台回复1,整理不易,给个关注点个赞吧,谢谢各位大佬!

这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/228601.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React 中虚拟DOM是什么,为什么需要它?

注意:本节主要讲React中的虚拟DOM,但是虚拟DOM并不是React中特有的内容。 1. React 中虚拟 DOM是什么? 虚拟DOM是对真实DOM的描述,虚拟DOM是JS对象,实际上就是 JSX 通过 babel 转换成 React.createElement()&#xff…

中缀表达式转后缀表达式与后缀表达式计算(详解)

**中缀表达式转后缀表达式的一般步骤如下: 1:创建一个空的栈和一个空的输出列表。 2:从左到右扫描中缀表达式的每个字符。 3:如果当前字符是操作数,则直接将其加入到输出列表中。 4:如果当前字符是运算符&a…

你是外包,麻烦不要偷吃零食,注意素质..

我自己没经历过外包,靠自己的所见所闻可能写出来的东西会很主观,所幸我有不少外包的读者,还有几个在外包工作或工作过的朋友,在跟她们深度交流之后,这这里聊一下我自己的一些看法。 注:本文不代表所有外包公…

Python接口自动化测试数据和代码分离解析

common中存放的是整个项目中公共使用的封装方法 从工程目录上可以看到区分 datas中专门存放测试数据(yml文件) cases中专门集中存放测试用例 ... 数据分离的第一步先找到工程项目路径 1 2 3 4 5 6 7 8 9 10 11 12 # -*- encoding: utf-8 -*- """ __Software…

智能运维相关算法总结

概念: 智能运维(AIOps)是基于已有的运维数据(日志、监控信息 、应用信息)并通过机器学习的方法来进一步解决自动化运维没办法解决的问题,其核心是机器学习和大数据平台。 目标: 事前预警&…

C++ day59 下一个更大元素Ⅱ 接雨水

题目1:503 下一个更大元素Ⅰ 题目链接:下一个更大元素Ⅱ 对题目的理解 返回循环数组中每个元素的下一个更大元素, 数字x的下一个更大元素是循环等的搜索它的最近的下一个更大的数 数组的中至少有一个元素 本题难点在于循环遍历这里&…

新手搭建知识付费平台必备攻略:如何以低成本实现高转化?

我有才知识付费平台 一、引言 随着知识经济的崛起,越来越多的知识提供者希望搭建自己的知识付费平台。然而,对于新手来说,如何以低成本、高效率地实现这一目标,同时满足自身需求并提高客户转化率,是一大挑战。本文将…

【面试经典150 | 二叉树】从前序与中序遍历序列构造二叉树

文章目录 写在前面Tag题目来源题目解读解题思路方法一:递归 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容…

Java数字化健康卫生智慧云HIS系统源码

基于云计算技术的B/S架构云HIS集挂号、处方、收费、取药、病历于一体,完全适配各类中小型医院、诊所。 一、云 HIS定义 1、云 HIS 系统是运用云计算、大数据、物联网等新兴信息技术,按照现代医疗卫生管理要求,在一定区域范围内以数字化形式提供医疗卫生…

软文营销全过程分享,助力企业提高宣传效率

数字化时代下,软文营销已经成为许多企业推广品牌的手段,但是在营销过程中大部分企业认为只需要写好文章进行发布就够了,这其实是错误的,只会浪费企业的时间精力。今天媒介盒子就分享软文营销全过程,助力企业提高宣传效…

cpu 300% 爆满 内存占用不高 排查

top查询 cpu最高的PID ps -ef | grep PID 查看具体哪一个jar服务 jstack -l PID > ./jstack.log 下载/打印进程的线程栈信息 可以加信息简单分析 或进一步 查看堆内存使用情况 jmap -heap Java进程id jstack.log 信息示例 Full thread dump Java HotSpot(TM) 64-Bit Se…

SpringMVC 案例

文章目录 前言1. 计算器1.1 准备前端代码1.2 测试前端代码1.3 完成后端代码1.4 验证程序 2. 留言板2.1 前端代码准备2.2 测试前端代码2.3 完成前后端交互代码2.4 完成后端代码2.5 案例测试2.6 完善前后端交互2.7 完善后端代码2.8 完整功能测试 lombok简单的方式添加Lombok工具3…

小视频怎么做成二维码?视频二维码3步生成

在日常工作和生活中经常会看到各种类型的小视频、短视频,比如网页、抖音等等的视频都是可以下载查看的。当我们想要将下载视频分享给多个人看时,生成二维码的方式会更加的方便,那么视频如何生成二维码呢?下面就将快捷生成二维码的…

spring boot 3.2 整合 keycloak

背景 项目中用到 keycloak,因此其他所有管理页面要集成 keycloak 做统一登录认证。 Keycloak 侧配置 容器方式启动 keycloak 服务端 docker run -d --name mykeycloak -p 8080:8080 -e KEYCLOAK_ADMINadmin -e KEYCLOAK_ADMIN_PASSWORDadmin ke…

LeetCode 每日一题 Day 6(DFS+BFS)

1466. 重新规划路线 n 座城市,从 0 到 n-1 编号,其间共有 n-1 条路线。因此,要想在两座不同城市之间旅行只有唯一一条路线可供选择(路线网形成一颗树)。去年,交通运输部决定重新规划路线,以改变…

【GEE笔记】在线分类流程,标注样本点、分类和精度评价

GEE在线分类流程 介绍 GEE(Google Earth Engine)是一个强大的地理信息处理平台,可以实现在线的遥感影像分析和处理。本文将介绍如何使用GEE进行在线的分类流程,包括标注样本点、分类和精度评价。本文以2020年5月至8月的哨兵2影像…

优秀案例 | 元宇宙双语财经科技主播“舒望”主持首届粤港澳大湾区元宇宙国际传播论坛

12月6日,由南方财经全媒体集团指导、大湾区元宇宙国际传播实验室(GBA MIC Lab)主办、南财国际传播中心和21世纪经济报道共同承办,以“多元共创开放共享”为主题的首届粤港澳大湾区元宇宙国际传播论坛在广州隆重开幕。 “立足湾区,…

【GEE笔记】随机森林特征重要性计算并排序

随机森林是一种基于多个决策树的集成学习方法,可以用于分类和回归问题。在gee中可以使用ee.Classifier.smileRandomForest()函数来创建一个随机森林分类器,并用它来对影像进行分类。 随机森林分类器有一个重要的属性,就是可以计算每个特征&a…

【沁恒蓝牙MESH】CH582串口中断内存溢出导致MCU频繁重启

本文主要记录了【沁恒蓝牙mesh】CH582串口中断内存溢出导致MCU频繁重启 由于开发疏忽,导致的数组内存溢出,是入门嵌入式开发经常忽视的错误,用以记录,共勉!! 目录 1. 遇到问题描述以及解决1.1 问题一&#…
最新文章