编写http接口api及接口自动化测试

2023-12-04

片言

此文中代码都是笔者工作中源码,所以不会很完整,主要摘常见场景的api片段用以举例说明

另:此文主要针对自动化测试人员,尤其有python基础阅读更佳。

笔者使用 python3.6 + postgresql10 + flask 0.12 的环境

场景介绍

我们要实现后台管理中的 用户管理 功能,实现对用户的增、修改、删除、查询操作。

文中场景省去登录和用户权限部分,但我会在接口代码片段中进行注释说明

接口:新增用户

(定义访问的http链接地址,以及请求使用的 method)    http://127.0.0.1:7070/guardian/users

 
@app.route('/guardian/users', methods=['POST'])    # 使用 POST 方法
@require_role('guardian_admin')    # 登录用户的角色权限必须是guardian_admin 此处是自定义的更角色管理中的设置管理员角色一致即可。不需要角色权限也可以注释此行即可
@login_required    # 验证用户登录 flask_login插件
def create_user():
    '''
    下面json串是新增时候前台表单提交的内容以及格式,也就是我们接口测试时候需要添加的测试数据
    {
            "user": {
                "domain_id": "default",
                "enabled": True,
                "name": "tsbc1",
                "password": "111111",
                "realname": "Ray",
                "email": "tsbc@vip.qq.com",
                "tel": "+86-029-88880000",
                "phone": "13800138000",
                "org_id": "7d22d25a-b648-4ad3-a834-2398eb989a9e",
                "org_array":[],
                "comments": "备注信息"
            }
        }
    '''
    try:
        domain_id = None
        user_name = None
        user_passwd = None
        project_id = None
        real_name = None
        email = None
        phone = None
        org_id = None
        org_array = None
        comments = None
        try:
            # 接收前端请求数据,并使用json.loads 把数据转换成Python可以读格式
            resq_obj = request.data
            resq_json = None
            if type(resq_obj) is bytes:
                resq_json = resq_obj.decode()
            else:
                resq_json = resq_obj
            user_obj = jsonpickle.loads(resq_json)    # 此处使用了jsonpickle的lib,使用json lib也是一样的
            logging.debug('create user {0} '.format(user_obj))
            if 'default_project_id' in user_obj['user']:
                project_id = user_obj['user']['default_project_id']
 
            domain_id = user_obj['user']['domain_id']
            user_name = user_obj['user']['name']
            user_passwd = user_obj['user']['password']
 
        except Exception as ee:
            abort(400)
            #raise ee
 
        if domain_id is not None and user_name is not None and user_passwd is not None:
            # 笔者使用 keystone 进行用户管理 此处在keystone创建帐号,然后获取id,把id及其它信息会存放在自定义的数据库表中
            resp = usermgt.create_user(domain_id, user_name, user_passwd, project_id)    # resp返回值是 dict 格式
            if 'id' in resp['user']:
                try:
                    # 把前端POST的表单值进行变量赋值 传给后台进行存库
                    user_id = resp['user']['id']
                    if 'realname' in user_obj['user']:
                        real_name = user_obj['user']['realname']
                    if 'email' in user_obj['user']:
                        email = user_obj['user']['email']
                    if 'tel' in user_obj['user']:
                        tel = user_obj['user']['tel']
                    if 'phone' in user_obj['user']:
                        phone = user_obj['user']['phone']
                    if 'org_id' in user_obj['user']:
                        org_id = user_obj['user']['org_id']
                    if 'org_array' in user_obj['user']:
                        org_array = user_obj['user']['org_array']
                    if 'comments' in user_obj['user']:
                        comments = user_obj['user']['comments']
 
                except Exception as e:
                    # raise e
                    abort(400)
                if user_obj is not None:
                    try:
                        # 调用方法进行后台存库
                        GuardianModelDao._save_update_users_info(user_id, user_name, real_name, email, tel, phone, org_id, org_array, comments)
                        return wrap_response(SUCCESS_MSG, 200)    # 执行成功 返回操作成功信息及状态码 200
                    except Exception as e:
                        LOG.debug(e)
                        abort(500)    # 否则 后台500 错误
            else:
                abort(500)

后台函数

用于实现对接口中传递数据进行处理入库、修改、查询等等。

 
 @classmethod
    def _save_update_users_info(cls, user_id, username, real_name, email, tel, phone, org_id, org_array, comments):
        LOG.debug('start create users info...')
        try:
            with TxConn() as conn: # 连接数据库
                with conn.cursor() as cursor:
                    # save user data
                    now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                    # 接收变量赋值 user_data
                    users_data = {
                        "user_id":user_id,
                        "username":username,
                        "realname":real_name,
                        "email":email,
                        "tel":tel,
                        "phone":phone,
                        "org":org_id,
                        "org_array":org_array,
                        "comments":comments,
                        "now_time":now_time
                    }
                    cursor.execute(cls.insert_users_info, users_data)    # 插入数据
                conn.commit()
        except Exception as e:
            LOG.exception('error saving users info', e)
            raise e

测试脚本(新增用户)

python unittest做单元测试

 
import unittest, requests
 
class GuardianTestCase(unittest.TestCase):
    guardian_base = 'http://127.0.0.1:7070'
    user_token = keystone.user_token('default', 'tsbc', '123456') # 调用keystone生成登录用户的token
    
def test_create_user_api(self):
        # 添加对应headers 及 tonken 用于数据传参和登录认证使用
        myheaders = {'Content-Type': 'application/json'}
        myheaders['X-Subject-Token'] = self.user_token
        # 接口测试数据
        user = {
            "user": {
                "domain_id": "default",
                "enabled": True,
                "name": "tsbc1",
                "password": "123456",
                "realname": "Ray",
                "email": "tsbc@123.com",
                "tel":"+86-029-88880000",
                "phone": "13800138000",
                "org_id": "7d22d25a-b648-4ad3-a834-2398eb989a9e",
                "org_array":None,
                "comments": "备注信息"
            }
        }
        # 使用requests的post方法进行请求路由
        _resp = requests.post(self.guardian_base + '/guardian/users', json=user, headers=myheaders, verify=True)
        resp_json = _resp.content
        # 对返回结果及状态进行校验
        if _resp.ok:
            self.assertIsNotNone(resp_json)
            LOG.info('create users, response: {0}'.format(resp_json))
        else:
            LOG.error('error create users, response: {0}, status: {1}'.format(resp_json, _resp.status_code))

接口:修改用户

修改用户和新增用户传递的参数差不多,使用的是http的patch请求,route要添加user_id的参数 ,其他实现和新增差不多代码不重复贴了

 
@app.route('/guardian/users/<string:user_id>', methods=['PATCH'])
@require_role('guardian_admin')
@login_required
def update_user(user_id):
    """
    此处省略接收请求数据代码
    """
    try:
            resp = usermgt.update_user(domain_id, user_id, username, user_passwd, project_id, enabled) # 更新keystone 用户密码、状态
            if resp is not None:
                # 更新用户基本信息与新增是同一个接口,执行SQL时使用PostGresql特性,相同user_id数据只更新不会再插入
                GuardianModelDao._save_update_users_info(user_id, username, real_name, email, tel, phone, org_id, org_array, comments)
                return wrap_response(SUCCESS_MSG, 200)    # 更新成功返回 200
        except Exception as e:
            LOG.exception('error modify user', e)
            abort(500)    # 更新失败500

测试脚本(修改用户)

 
def test_update_user_api(self):
 
        myheaders = {'Content-Type': 'application/json'}
        myheaders['X-Subject-Token'] = self.user_token
 
        user = {
            "user": {
                "domain_id": "default",
                "enabled": True,
                "name": "tsbc1",
                "password": "111111",
                "realname": "xioohua",
                "email": "haoydun@123.com",
                "tel": "+86-029-88880000",
                "phone": "13800138000",
                "org_id": "7d22d25a-b648-4ad3-a834-2398eb989a9e",
                "comments": "备注信息"
            }
        }
 
        _resp = requests.patch(self.guardian_base + '/guardian/users/0d26176579e94d558c4c2d864b003241',   # 路由中添加要修改的用户ID requests使用 patch方法
                               json=user, headers=myheaders, verify=True)
        resp_json = _resp.content
        # 返回值进行校验
        if _resp.ok:
            self.assertIsNotNone(resp_json)
            LOG.info('update users, response: {0}'.format(resp_json))
        else:
            LOG.error('error update users, response: {0}, status: {1}'.format(resp_json, _resp.status_code))

接口:查询用户

根据用户名查询用户,使用http的get请求

 
@app.route('/guardian/users/<string:user_name>', methods=['GET'])    # 查询使用 GET 方法
@require_role('guardian_admin')
@login_required
def query_user_by_username(user_name):
 
    try:
        user_info = GuardianModelDao._query_users_info_by_name(user_name)    # 调用后台查询函数
        if len(user_info):
            return wrap_response(jsonpickle.dumps(user_info), 200)    # 成功返回200 并把返回内容转换成 json格式
        else:
            return wrap_response("[]", 200)   # 否则返回空
    except Exception as e:
        LOG.exception('error query user by name', e)
        abort(500)
后台函数
 
@classmethod
    def _query_users_info_by_id(cls, user_id):
        LOG.debug('start list users info...')
        users = []
        with TxConn() as conn:
            try:
                with conn.cursor() as cursor:
                    data = (user_id,)
                    cursor.execute(cls.query_users_info_by_id, data)
                    # 查询结构如果是行数据,放进list中进行返回
                    for (user_id, real_name, email, tel, phone, org_id, org_array, comments, create_time, update_time) in cursor:
                        user = Users(user_id, real_name, email, tel, phone, org_id, org_array, comments, create_time, update_time)
                        users.append(user)
            except Exception as e:
                LOG.exception('error query users !')
                raise e
        return users

测试脚本(查询用户)

 
 def test_query_user_api(self):
 
        myheaders = {'Content-Type': 'application/json'}
        myheaders['X-Subject-Token'] = self.user_token
 
        _resp = requests.get(self.guardian_base + '/guardian/users/tsbc', headers=myheaders, verify=True) # 链接中加入用户名
        resp_json = _resp.text
        # 验证判断
        if _resp.ok:
            self.assertIsNotNone(resp_json)
            LOG.info('query users, response: {0}'.format(resp_json))
        else:
            LOG.error('error query users, response: {0}, status: {1}'.format(resp_json, _resp.status_code))
接口:删除用户

根据用户ID进行删除,使用http的delete请求

 
@app.route('/guardian/users/<string:user_id>', methods=['DELETE']) # 传入用户id 使用 delete请求
@require_role('guardian_admin')
@login_required
def delete_user(user_id):
    if user_id is None:
        abort(400)
    try:
        s_code = usermgt.delete_user(user_id)
        if s_code == 204:
            return wrap_response(SUCCESS_MSG, status=s_code) # 返回状态码
    except Exception as e:
        LOG.exception('error delete users info', e)
        abort(500)

后台函数

 
def delete_user(user_id):
    myheaders = {'Content-Type': 'application/json'}
    myheaders['X-Auth-Token'] = settings.KEYSTONE_ADMIN_TOKEN
    _resp = requests.delete(settings.KEYSTONE_BASE + '/v3/users/'+user_id,
                            headers=myheaders, verify=False)
 
    if _resp.status_code == 204:
        LOG.debug('delete users -- response {0}'.format(_resp))
        return _resp.status_code
    else:
        LOG.error('error list users, response: {0}'.format(_resp))
        raise KeystoneException('error delete user {0} with response status {1}'
                                .format(user_id, _resp.status_code), _resp.status_code)

测试脚本(删除用户)

 
def test_delete_users_api(self):
 
        myheaders = {'Content-Type': 'application/json'}
        myheaders['X-Subject-Token'] = self.user_token
        _resp = requests.delete(self.guardian_base + '/guardian/users/tsbc1', headers=myheaders, # 使用 delete 请求
                                verify=True)
        resp_json = _resp.content
        # 根据返回状态进行校验
        if _resp.ok:
            self.assertIsNotNone(resp_json)
            LOG.info('delete users api, response: {0}'.format(resp_json))
        else:
            LOG.error('error delete users api, response: {0}, status: {1}'.format(resp_json, _resp.status_code))
下面提供给前端API文档
## CREATE USER

1. URL:' /guardian/users'

2. METHOD: POST

3. body:

 
{
            "user": {
                "domain_id": "default",
                "enabled": True,
                "name": "tsbc1",
                "password": "111111",
                "realname": "Ray",
                "email": "haoydun@123.com",
                "tel":"+86-029-88880000",
                "phone": "13800138000",
                "org_id": "7d22d25a-b648-4ad3-a834-2398eb989a9e",
                "org_array": null,
                "comments": "备注信息"
            }
}
##  UPDATE USER

1. URL:' /guardian/users/<string:user_id>'

2. METHOD: PATCH2. body:

 
{
            "user": {
                "domain_id": "default",
                "enabled": True,
                "name": "tsbc1",
                "password": "111111",
                "realname": "Ray",
                "email": "tsbc@vip.qq.com",
                "tel":"+86-029-88880000",
                "phone": "13800138000",
                "org_id": "7d22d25a-b648-4ad3-a834-2398eb989a9e",
                "org_array": null,
                "comments": "备注信息"
            }
  }

该接口可以用于修改密码,禁用用户

## QUERY USER BY NAME

1. URL:' /guardian/users/<string:user_name>'

2. METHOD: GET

## DELETE USER

1. URL: '/guardian/users/<string:user_id>'

2. METHOD: DELETE

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编写http接口api及接口自动化测试 的相关文章

  • 在电子邮件中使用协议相对 URL 安全吗?

    关于在 HTML 中使用协议相对 URL 已有讨论 1 但是电子邮件呢 电子邮件客户端或 Gmail 等服务提供商在 HTML 电子邮件中使用时是否会删除或修改协议相对 URL 1 我可以将所有 http 链接更改为 吗 https sta
  • TRESTRequest:是否可以在 POST 请求中使用自定义媒体类型?

    例如 我们有一个 API 需要我们自己的供应商特定内容类型application vnd xxxx custom custom data json但查看 REST Client 的源代码 它似乎总是默认为 REST Types 中的 Con
  • 把自己限制在HTTP1.0有什么用吗?

    我负责构建一些工具来帮助最终用户测试为什么他们的浏览器可能无法与网站配合使用 我被告知它可能不起作用的原因之一是 需要 HTTP1 1 这一行 我浏览了大多数浏览器选项 只浏览了 IE 版本 6 及更高版本 even 9 允许您禁用 HTT
  • JavaScript:发送 POST,重定向到响应

    我有一个带有 onclick 的图像 当单击事件触发时 我想发送 HTTP POST 并将 window location 重定向到 POST 的响应 我怎样才能做到这一点 只需将按钮绑定到表单元素的提交方法 重定向就会自然发生
  • 通过 HTTPS 包含 Twitter Widgets.js

    当我们包含以下内容时 我在我们网站上的 HTTPS 服务页面上的混合内容方面遇到了一个小问题http platform twitter com widgets js http platform twitter com widgets js
  • WCF - 进行多次调用时随机客户端超时

    我有一个WPF客户端通过以下方式请求数据WCF服务托管于IIS 7 服务方法调用存储过程 SQL 2012 using EF检索一些数据 由于需要加载大量数据 因此客户端会多次调用服务方法 以 分解 数据加载并避免大量负载和超时 我们使用生
  • 在 Restangular 中发送 GET 参数

    我在用着矩形 https github com mgonto restangular在我的项目和早期的项目中 这段代码对于检索对象数组效果很好 var params name Stack surname Overflow var servi
  • Express.js在控制器中获取http方法

    我正在构建一个注册表单 本地护照作为身份验证 表单作为表单助手 因为注册只知道 GET 和 POST 我想在一个函数中完成整个处理 换句话说 我正在寻找类似的东西 exports register function req res if r
  • 从开放的 HTTP 流中读取数据

    我正在尝试使用 NET WebRequest WebResponse 类来访问 Twitter 流 API 此处 http stream twitter com spritzer json 我需要能够打开连接并从打开的连接中增量读取数据 目
  • C# - 如何进行 HTTP 调用

    我想对网站进行 HTTP 调用 我只需要点击 URL 不想上传或下载任何数据 最简单 最快的方法是什么 我尝试了下面的代码 但它很慢 并且在第二次重复请求后 它只是超时 59 秒 然后恢复 WebRequest webRequest Web
  • 减少1000张图片的HTTP请求?

    我知道这个问题可能听起来有点疯狂 但我想也许有人会想出一个聪明的主意 假设您在一个 HTML 页面上有 1000 个缩略图 图像大小约为5 10 kb 有没有办法在单个请求中加载所有图像 以某种方式将所有图像压缩到一个文件中 或者您对该主题
  • Golang 优雅地关闭 HTTP 服务器并进行错误处理

    我正在让我的 HTTP 服务器正常关闭 我从帖子中获取了提示here https stackoverflow com questions 39320025 how to stop http listenandserve 并且到目前为止已经像
  • 服务器返回网页 404,但页面在浏览器中显示正常 - 为什么?

    一个奇怪的网页横亘在我面前 作为一名开发人员 我必须解开这个谜团 在任何浏览器中访问网页时 一切似乎都很正常 网页按预期显示 但是当查看控制台时 服务器实际上返回了 404 状态代码 那么浏览器为什么要渲染页面呢 查看正文显示返回了有效的
  • 通过 HTTPS 加载页面但请求不安全的 XMLHttpRequest 端点

    我有一个页面 上面有一些 D3 javascript 该页面位于 HTTPS 网站内 但证书是自签名的 当我加载页面时 我的 D3 可视化效果不显示 并且出现错误 混合内容 页面位于 https integration jsite com
  • 将 HttpApi 与 I/O 完成端口结合使用

    我刚刚偶然发现了微软的HTTP 服务器 API http msdn microsoft com en us library aa364510 28v vs 85 29 aspx 简介中写道 HTTP 服务器 API 使应用程序能够通过 HT
  • Android - API 请求

    我开发了一个应用程序 它也在 iPhone 上 问题出在 api 请求上 我为所有请求设置了超时 有时会出现 30 60 秒的中断 看起来这个应用程序执行了几个请求 然后就中断了 一直超时 大约 45 秒后一切正常 不知道是服务器问题还是安
  • 在java中轮询Http服务器(重复发送http get请求)

    当对其进行 REST 调用时 我的 Web 服务器会发送一些信息 我想不断轮询该服务器 间隔5秒后重复发送HTTP GET请求 以检查返回的信息是否有任何变化 做到这一点最有效的方法是什么 您能提供一些代码示例吗 请注意 我只想开发客户端代
  • AJAX 发送数据到 Node.js 服务器

    我尝试使用 AJAX 将数据发送到 Node js 服务器 但不断遇到同样的问题 即接收问题 这是客户端 JavaScript AJAX 代码 var objects function return new XMLHttpRequest f
  • 如何转义角度 HttpParams?

    在 Angular 服务中 我使用 HttpParams 将字符串发送到服务 get phone string Observable
  • 如何使用 python 的 http.client 准确读取一个响应块?

    Using http client在 Python 3 3 或任何其他内置 python HTTP 客户端库 中 如何一次读取一个分块 HTTP 响应一个 HTTP 块 我正在扩展现有的测试装置 使用 python 编写 http clie

随机推荐

  • co域名是什么

    co域名是什么本篇文章给大家分享的是有关co域名是什么 小编觉得挺实用的 因此分享给大家学习 希望大家阅读完这篇文章后可以有 所收获 话不多说 跟着小编一起来看看吧 co域名后缀是哥伦比亚的国家顶级域名后缀 是因特网域名治理机构ICANN
  • 软件测试-软件缺陷有哪些,一文贯彻到底

    软件缺陷 软件缺陷 又称之为 Bug 即计算机软件或程序中存在的某种破坏正常运行能力的问题 错误 或者隐藏的功能缺陷 表现形式A 软件没有实现产品规格说明书所要求的功能模块 表现形式B 软件中出现了产品规格说明指明不应该出现的错误 表现形式
  • 【2024年趋势】推荐5个好用的产品手册制作工具

    随着科技的快速发展 人们对于网站产品手册的需求也日益增加 一份详细且易用的产品手册可以帮助用户更好地了解和使用产品 提高用户满意度和忠诚度 之前整理了一期关于2023年我推荐的一些知识库软件 已经12月了 最近我也去关注了一些2024年的趋
  • 掌握未来设计趋势,开启AutoCAD2020创新之旅!

    随着科技的不断发展 设计行业也在迅速演进 为满足设计师们日益增长的需求 Autodesk AutoCAD2020应运而生 作为一款全球领先的设计软件 AutoCAD2020不仅拥有更加强大的功能和更高效的性能 还融入了一系列的智能化设计工具
  • 简单在生活中使用CHAT写心得

    问CHAT 农产品品牌建设和数字供销对于供销社有什么意义 CHAT回复 对于供销社来说 农产品品牌建设和数字供销的重要性主要体现在以下几个方面 1 提升农产品价值 通过品牌建设 可以提升农产品的附加值和市场竞争力 有利于增强农民的收入 推动
  • Unittest单元测试之unittest用例执行顺序

    用例执行顺序 当在一个测试类或多个测试模块下 用例数量较多时 unittest在执行用例 test xxx 时 并不是按从上到下的顺序执行 有特定的顺序 unittest框架默认根据ACSII码的顺序加载测试用例 数字与字母的顺序为 0 9
  • offer决赛圈,吉利成都 vs 理想上海

  • Leetcode 剑指 Offer II 055. 二叉搜索树迭代器

    题目难度 中等原题链接今天继续更新 Leetcode 的剑指 Offer 专项突击版 系列 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列 include
  • 动态BGP与静态BGP的区别

    动态BGP与静态BGP的区别 动态BGP与静态BGP的区别 1 静态BGP功能简单 其带宽功能 可以实现多网接入 但路径上只有通向几大运营商的固定的几条路径 当某个运营商方向 的某个路由节点出现故障时 会导致某个运营商方向不能正常通信 造成
  • 题解 | #糖糖别胡说,我真的不是签到题目#

    可以提前把施法后的b算出来 因为前面的结果会影响后面的判断 include
  • 用通俗的方法讲解:大模型微调训练详细说明(附理论+实践代码)

    本文内容如下 介绍了大模型训练的微调方法 包括prompt tuning prefix tuning LoRA p tuning和AdaLoRA等 介绍了使用deepspeed和LoRA进行大模型训练的相关代码 给出了petals的介绍 它
  • Jmeter工具+ant+jenkins实现持续集成

    ant jenkins持续集成 一 下载并配置jmeter 首先下载jmeter工具 并配置好环境变量 参考 jmeter默认保存的是 jtl格式的文件 要设置一下bin jmeter properties 文件内容 保存jmeter sa
  • 题解 | #字符串最后一个单词的长度#

  • 题解 | #求小球落地5次后所经历的路程和第5次反弹的高度#

    可以说一说流程吗 信息科技岗有没有问专业问题 l apple ice cream watermelon chips hotdogs hotpot while len include
  • 美国站群服务器是什么 有哪些用途

    美国站群服务器是什么 有哪些用途 许多从事海外业务的网站管理员会租用外国站群服务器来建立自己的海外网站 一些新手用户不明白什么是站群服务器 站群服务器的作用是什么 本文总结了站群服务器在网站优化和获取高质量流量方面的一些作用 希望能帮助您更
  • 基于java的出租车计价器系统设计与实现

    基于java的出租车计价器系统设计与实现 I 引言 A 研究背景和动机 基于Java的出租车计价器系统设计与实现的研究背景和动机 可以归纳为以下几个方面 首先 Java作为一种广泛应用的编程语言 具有优秀的跨平台性 高性能和可靠性等特点 因
  • excel+requests管理测试用例接口自动化框架

    背景 某项目有多个接口 之前使用的unittest框架来管理测试用例 将每个接口的用例封装成一个py文件 接口有数据或者字段变动后 需要去每个py文件中找出变动的接口测试用例 维护起来不方便 为了便于接口变动后维护 使用excel来管理测试
  • 想找一个比wordpress更好操作的帮助中心搭建工具?国内我更推荐这个······

    随着互联网的普及 客户对在线帮助中心的需求不断增加 为了提供更好的客户体验 许多企业开始寻找比WordPress更易操作且功能更强大的帮助中心搭建工具 国内的 HelpLook gt https portal helplook net lo
  • 编写http接口api及接口自动化测试

    片言 此文中代码都是笔者工作中源码 所以不会很完整 主要摘常见场景的api片段用以举例说明 另 此文主要针对自动化测试人员 尤其有python基础阅读更佳 笔者使用 python3 6 postgresql10 flask 0 12 的环境
  • Fiddler抓包工具之fiddler的介绍及安装

    简介 Fiddler是比较好用的web代理调试工具之一 它能记录并检查所有客户端与服务端的HTTP HTTPS请求 能够设置断点 篡改及伪造Request Response的数据 修改hosts 限制网速 http请求性能统计 简单并发 接