博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在实际工作中使用requests+unittest进行接口测试
阅读量:5030 次
发布时间:2019-06-12

本文共 6981 字,大约阅读时间需要 23 分钟。

 之前学习python做接口测试时,用的时requests+excel的方式来进行接口测试,后来在工作中也用unittest来做了一个项目的接口测试,接口测试用例完全基于unittest来编写,把大致步骤记录一下。

项目背景

之前公司的测试并没有在前期就介入项目,即使是接口测试,也是在研发人员完成项目开发后再进行的接口校验,其实更接近于验证一下接口功能是否正常实现了,一般这种工作我更喜欢使用postman来进行,一个一个把接口录入postman,每个都单独校验一下,最终也会形成一套测试脚本(对于没有代码能力又要进行接口测试的人来说简直是神器)。后来再论坛看其他人的经验贴时,发现其实对于公司这种接口比较少的项目,也完全可以用python自带的unittest来写测试用例,一个接口写作一个py文件,其实也很简洁,相对于requests+excel的方式省去了读取/解析excel文件的步骤,维护起来也不麻烦。

结构说明

base_data: 封装了一些基础数据,如固定的ip地址、端口(方便后期修改)

common_utils: 存放了一些配置文件、读取配置文件的方法、发送请求的方法

reports:存放测试报告

test_suits: 存放接口测试用例

run_report.py: 最终运行文件,即调用测试用例,执行后生成报告

每个模块下的具体内容

1.common_utils

config.ini 配置文件 [URL]# url = http://192.168.XXX:7001url  = http://192.168.XXX:8080
read_config.py 读取配置文件的方法# -*- coding:utf-8 -*-import configparserimport osclass ReadConfig:    def __init__(self, filepath=None):        if filepath:            configpath1 = filepath        else:            root_dir1 = os.path.dirname(__file__)  # 获取当前脚本的目录            configpath1 = os.path.join(root_dir1, "config.ini")  # 拼接路径            # print(root_dir1)            # root_dir = os.path.dirname(os.path.abspath('.')) # 获取当前脚本所在目录的上一级目录            # configpath = os.path.join(root_dir, "common_utils/config.ini") # 拼接路径            # print(root_dir)        self.cf = configparser.ConfigParser()        self.cf.read(configpath1)    def get_host(self, param):        value = self.cf.get("URL", param)        return valuebase_url = ReadConfig()# if __name__ == '__main__':#     test = ReadConfig()#     t = test.get_host("url")#     print(t)    # print(base_url.get_host("URL"))
send_request.py请求方法类 # -*- coding:utf-8 -*-import requestsimport jsonfrom requests.exceptions import RequestExceptionclass RunMethod:    """定义一个执行接口请求的类"""    @staticmethod    def send_get(url, data=None, header=None):        response = requests.get(url=url, params=data, headers=header, timeout=20)        try:            if response.status_code == 200:                r = response                return r            else:                return None        except RequestException:            print("请求失败")            return None    @staticmethod    def send_post(url, data=None, header=None):        response = requests.post(url=url, data=data, headers=header, timeout=20)        try:            if response.status_code == 200:                r = response                return r            else:                return None        except RequestException:            print("请求失败")            return None    def run_main(self, method, url, data=None, header=None):        if method == "GET":            res = self.send_get(url, data, header)        else:            res = self.send_post(url, data, header)        # return json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)        return resif __name__ == '__main__':    url = "http://192.168.XXX:7001/ApprLicenseInterface/saveFile.v"    data = {
'ATTACH_SIZE': "36243", 'ATTACH_URL': "/mnt/MDFilesPath/APPR_STUFF_ATTACH/B2018120709470002/Rectangle.png", 'ATTACH_CREATOR': "", 'PARENTID': "-1", 'ATTACH_NAME': "67d06265bb814e6aa0f8f87913ab4f4e.pdf"} t = RunMethod() print(t.run_main("GET", url, data)) print(type(t.run_main("GET", url, data)))

2.base_data

base_data.py基础数据,从配置文件取数据
# -*- coding:utf-8 -*- from common_utils.read_config import ReadConfig import os class BaseData:     def __init__(self):         self.data = ReadConfig()     def get_ip(self):         """从配置文件中获取固定ip"""         ip = self.data.get_host("url")         return ip base_data = BaseData() # print(base_data.get_ip())

3.test_suits

 

这里面就是存放的接口测试用例了,一个文件代表一个接口,每个文件中根据实际情况存在多条用例(根据传参不同来组合)

注意:为了再后面往套件中添加用例文件,为每个用例文件都加了test_前缀;

说下遇到的一个问题:因为接口文档中每个接口都有一个编号,如下

所以开始我的命名方式是 test_5.2.1.1+接口名称,然后发现在把用例添加到测试套件时总是识别不到,后来把数字去掉才可以,至今不知道什么原因导致的。。。

一个例子# -*- coding:utf-8 -*-import unittestfrom common_utils.send_request import RunMethodfrom base_data.base_data import *import jsonrun = RunMethod()class Test(unittest.TestCase):    """ 5.2.1.3、依职能查验用证:通过目录编码以及身份证件号码获取证照"""    @classmethod    def setUpClass(cls):        cls.url = base_data.get_ip() + "/XXX/licenseList/identity.v"    @classmethod    def tearDownClass(cls):        pass    def test01(self):        """参数正常"""        data = {
"licenseDirNum":"123456789", "identityNumbers":"120101198001010098"} r = run.run_main("GET", self.url, data) res = r.json() print(json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)) self.assertEqual("200", res["status"]) self.assertNotEqual([], res["data"]["dataList"]) # 判断dataList不为空 def test02(self): """licenseDirNum为空""" data = {
"licenseDirNum":"", "identityNumbers":"120101198001010098"} r = run.run_main("GET", self.url, data) res = r.json() print(json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)) self.assertEqual("传入的参数:(licenseDirNum)不能为空", res["desc"]) self.assertTrue(res["data"] is None) # 判断返回结果的data值为空 self.assertIsNone(res["data"]) # 判断返回结果的data值为空 # self.assertNotEqual([], res["data"]["dataList"]) def test03(self): """identityNumbers为空""" data = {
"licenseDirNum": "123456789", "identityNumbers": ""} r = run.run_main("GET", self.url, data) res = r.json() print(json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)) self.assertEqual("传入的参数:(identityNumbers)不能为空", res["desc"]) self.assertTrue(res["data"] is None) # 判断返回结果的data值为空if __name__ == '__main__': suite = unittest.TestSuite() # 调用unittest的TestSuite(),理解为管理case的一个容器(测试套件) suite.addTest(Test('test01')) # 向测试套件中添加用例,"TestMethod"是上面定义的类名,"test01"是用例名 runner = unittest.TextTestRunner() runner.run(suite) # 执行套件中的用例

 4.run_report.py

# coding: utf-8# author: hmkimport HTMLTestRunnerimport unittestimport time, osroot_dir = os.path.dirname(os.path.abspath(__file__))  # 获取当前脚本的目录case_dir = root_dir + '/test_suits'  # 根据项目所在路径,找到用例所在的相对项目的路径# case_dir1 = 'E:/5.coding\电子证照库接口/test_suits\电子证照类'print(root_dir)print(case_dir)suits = unittest.defaultTestLoader.discover(case_dir, pattern='test_*.py', top_level_dir=None) # 加载用例,用例文件名最好不要有数字,否则导致识别不到suit = unittest.TestLoader().discover(case_dir)  # 加载用例"""1.case_dir即测试用例所在目录2.pattern='test_*.py' :表示用例文件名的匹配原则,“*”表示任意多个字符3.top_level_dir=None:测试模块的顶层目录。如果没顶层目录(也就是说测试用例不是放在多级目录中),默认为 None"""if __name__ == '__main__':    now_time = time.strftime("%Y-%m-%d %H-%M-%S")    filename = root_dir + '/reports/' + now_time + '_result.html'  # 定义报告文件    # fp = open(filename, 'wb')    # runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='电子证照库接口测试报告',description='测试结果如下: ')    # runner.run(suit)    # fp.close()  # 普通方式打开文件    with open(filename, 'wb') as fp:        """使用withopen操作文件"""        runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='电子证照库接口测试报告', description='测试结果如下: ')        runner.run(suits)

最后执行run_report.py即可运行全部接口用例,得到测试报告

 

转载于:https://www.cnblogs.com/hanmk/p/10969938.html

你可能感兴趣的文章
一个简单的日志函数C++
查看>>
Java 8 中如何优雅的处理集合
查看>>
IOS程序的启动过程
查看>>
连接Linux下 XAMPP集成环境中部署的禅道的数据库MariaDB
查看>>
Java操作Excel和Word
查看>>
Oracle 体系结构之ORACLE物理结构
查看>>
ORA-12538: TNS: no such protocol adapter
查看>>
盒子模型
查看>>
局域网协议
查看>>
[HNOI2012]永无乡 线段树合并
查看>>
Spring整合hibernate:3、使用XML进行声明式的事务管理
查看>>
SqlServer之Convert 函数应用格式化日期(转)
查看>>
软件测试领域中的10个生存和发展技巧
查看>>
Camera前后摄像头同时预览
查看>>
HDU 1856
查看>>
课堂作业01--架构师的职责
查看>>
iOS计算富文本(NSMutableAttributedString)高度
查看>>
2017/09/15 ( 框架2)
查看>>
Centos下源码安装git
查看>>
gulp-rev-append md5版本号
查看>>