HttpRunner 使用小结

news2024/11/17 17:38:00

目录

https 请求证书验证

2.0.3 (2019-02-24)

代理调试

$ 符引用

json 响应中数组的提取和断言

text/html 响应的提取和断言

testcase 之间传递参数

2.2.2 (2019-06-26)

复用 cookies 和 token

1. 每个 testcase 登录一次

2. 将 cookies 或 token 写入文件,读取时按需刷新

cookies

token


前言: 最近项目要求快速完成接口自动化测试,因时间有限,经过考察后决定使用开箱即用的 httprunner,在使用过程同时也顺便总结了一些较为常见的问题和用法,在此记录一下。

为避免业务信息泄漏,文中某些 api 例子使用 httpbin.org,后续使用过程中如有新的内容,将持续更新此文。

https 请求证书验证

在对 https 接口进行测试时如果请求经过代理则可能会有 certificate verify failed 的报错,如:

ERROR: test_0000_000 (httprunner.api.TestSequense)
---------------------------------------------------------------------
Traceback (most recent call last):
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

原因是 request 模块发送请求函数有个参数 verify 值默认为 True.
使用 httprunner 则可在用例 yml 或 json 文件中将 config 或 teststep 中该参数设置为 False 跳过证书验证。

-   config:
        ...
        verify: False
-   test:
        ...
        request:
            verify: False

官方 changlog 中也描述过修复之后的这两处设置优先级:

2.0.3 (2019-02-24)

Bugfixes

  • fix verify priority: teststep > config

代理调试

httprunner 库本身没有提供设置代理的接口,但是底层使用了 urllib.requests 等库,可以设置 HTTP_PROXY 和 HTTPS_PROXY 环境变量,常用的网络库会自动识别这些环境变量,使用变量设置的代理发起请求:

httprunner 本身支持多种环境变量设置与读取方式,用法参考:https://cn.httprunner.org/prepare/dot-env/

e.g. 日常调试使用代理(如 charles 等工具)可在 debugtalk.py 开头加上

import os

os.environ['http_proxy'] = 'http://127.0.0.1:8888'
os.environ['https_proxy'] = 'https://127.0.0.1:8888'

$ 符引用

在 httprunner 中,$ 符被用来引用变量或函数,如果遇到需要将 $ 当成一个普通字符来使用时则可以通过 $$ 来表示一个普通 $ 字符而不是引用。

参考源码 httprunner/parser.py 第 598~603 行:

# content is in string format here
if not is_var_or_func_exist(content):
    # content is neither variable nor function
    # replace $$ notation with $ and consider it as normal char.
    # e.g. abc => abc, abc$$def => abc$def, abc$$$$def$$h => abc$$def$h
    return content.replace("$$", "$")

e.g.

# 在下面的 testcase yaml 文件中,command 变量中的 $$5 则代表 $5 ,否则只写为 $5,解析时则会去找变量名为 5 的变量,如果该变量不存在,则会报错。
- config:
    name: xxxx

- test:
    name: xxxx
    api: api/xx/xxxx.yaml
    variables:
      command: ifconfig | awk '{print $$5}'

Issue
但在这里,我也遇到一个问题,当我把变量设置放在 - config 中时,如:

- config:
    name: xxxx
    variables:
      command: ifconfig | awk '{print $$5}'

- test:
    name: xxxx
    api: api/xx/xxxx.yaml

$$ 并没有被当成普通的 $,而是报错变量未找到

File "/Users/mac/application/miniconda/envs/httprunner/lib/python3.7/site-packages/httprunner/parser.py", line 508, in __parse
    raise exceptions.VariableNotFound(var_name)
httprunner.exceptions.VariableNotFound: 5

该问题已向代码库提交 Issue: 在 testcase yaml 文件 - config 中为变量设置值时使用 $$ 未转换为普通的 $ · Issue #657 · httprunner/httprunner · GitHub

json 响应中数组的提取和断言

对于包含数组的 Json 响应,如下

# api 地址:https://httpbin.org/#/Response_formats/get_json

{
  "slideshow": {
    "author": "Yours Truly",
    "date": "date of publication",
    "slides": [
      {
        "title": "Wake up to WonderWidgets!",
        "type": "all"
      },
      {
        "items": [
          "Why <em>WonderWidgets</em> are great",
          "Who <em>buys</em> WonderWidgets"
        ],
        "title": "Overview",
        "type": "all"
      }
    ],
    "title": "Sample Slide Show"
  }
}

如果需要在 extract 或 validate 中对 "title": "Wake up to WonderWidgets!" 字段进行断言,提取方式可为 content.slideshow.slides.0.title (其中数字 0 为取数组中的第 1 位,序号以 0 开始):

e.g.

- config:
    name: testcase description
    verify: False

- test:
    name: /json
    request:
      method: GET
      url: https://httpbin.org/json
    extract:
      title: content.slideshow.slides.0.title
    validate:
      - eq:
          - status_code
          - 200
      - eq:
          - headers.Content-Type
          - application/json
      - eq:
          - content.slideshow.slides.0.title
          - 'Wake up to WonderWidgets!'

text/html 响应的提取和断言

对于文本内容和 html 响应需要对关键字进行提取和断言,可使用正则表达式进行匹配查找,有 html 响应内容如下:

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
      <h1>Herman Melville - Moby-Dick</h1>

      <div>
        <p>
          Availing himself of the mild, summer-cool weather that now reigned in these latitudes, and in preparation for the peculiarly active pursuits shortly to be anticipated, Perth, the begrimed, blistered old blacksmith, had not removed his portable forge to the hold again, after concluding his contributory work for Ahab's leg, but still retained it on deck, fast lashed to ringbolts by the foremast;        
        </p>
      </div>
  </body>

需要对文中关键字 summer-cool 进行断言,则可以使用正则表达式分组的方式对单词进行提取:

- config:
    name: testcase description
    verify: False

- test:
    name: /html
    request:
      method: GET
      url: https://httpbin.org/html
    extract:
      key: Availing himself of the mild, (.+) weather that now reigned in these latitudes
    validate:
      - eq:
          - status_code
          - 200
      - eq:
          - headers.Content-Type
          - text/html; charset=utf-8
      - eq:
          - $key
          - summer-cool

这个方法原理是通过正则分组,默认提取第一个分组匹配到的内容,用法类似于 loadrunner 的左右边界提取。

testcase 之间传递参数

使用 output/export 和 extract 可以在 testcase 之间传递参数
testcase 级的变量:

  • config 中设置的 variables
  • teststep 中 extract 提取的

可以在 testcase 的 - config 中通过 output 或者 export (2.2.2 版本添加) 将其暴露,然后在该 testcase 被引用时通过 extract 将变量提取出来使用。

- config:
    name: testcase description
    verify: False
    variables:
      configVar: configVar
    export:
      - key
      - configVar
      - teststepVar

- test:
    name: /html
    request:
      method: GET
      url: https://httpbin.org/html
    variables:
      teststepVar: teststepVar
    extract:
      key: Availing himself of the mild, (.+) weather that now reigned in these latitudes
    validate:
      - eq:
          - status_code
          - 200
      - eq:
          - headers.Content-Type
          - text/html; charset=utf-8

执行结果

# hrun output message
WARNING  variable 'teststepVar' can not be found in variables mapping, failed to export!
INFO     
==================== Output ====================
Variable         : Value
---------------- : -----------------------------
key              : summer-cool
configVar        : configVar
------------------------------------------------

在 teststep 中引用以上 testcase:

- config:
    name: testcase description
    verify: False

- test:
    name: /html
    testcase: testcases/html.yaml
    extract:
      - key
      - configVar
    validate:
      - eq:
          - $key
          - summer-cool

- test:
    name: /json
    request:
      method: GET
      url: https://httpbin.org/json
    validate:
      - eq:
          - $configVar
          - configVar

2.2.2 版本 CHANGELOG 中对此处用法做了相关说明:

2.2.2 (2019-06-26)

Changed

  • extract is used to replace output when passing former teststep’s (as a testcase) export value to next teststep
  • export is used to replace output in testcase config

复用 cookies 和 token

很多时候测试 api ,我们并不希望频繁登录获得授权,这个时候就需要复用 cookies 和 token 。

1. 每个 testcase 登录一次

在 httprunner 中如果不同 api 是在同一个 testcase 的不同步骤,那么只需要在一个 teststep 登录授权,则其他的 teststep 是可以共用授权,推测应该是 testcase 里共用同一个 requests.seesion 。

2. 将 cookies 或 token 写入文件,读取时按需刷新

cookies

在 debugtalk.py 文件中增加两个函数,generate_cookies 用于在读取文件中的 cookies,teardown_saveCookies 用于在 login.yaml 中保存 cookies 内容到文件。

import time
import requests
from httprunner.api import HttpRunner

COOKIES_PATH = r'xxx/xxx/cookies'

def generate_cookies():
    if (not os.path.exists(COOKIES_PATH)) or (
            3600 < int(time.time()) - int(os.path.getctime(COOKIES_PATH))):
        # cookies 文件不存在 或 最后修改时间超过 3600 秒 (1小时) 则重新登录刷新 cookies
        runner = HttpRunner()
        runner.run(r'api/login.yaml')
    with open(COOKIES_PATH, 'r') as f:
        cookies: str = f.read()
    return cookies

def teardown_saveCookies(response: requests.Response):
    """保存 cookies 到文件给其他 api 调用"""
    cookies: dict = response.cookies
    foo: list = []
    # 遍历 cookies 拆分 dict 并拼接为特定格式的 str
    # 如: server=xxxxx; sid=xxxxxx; track=xxxxx; 
    for k, v in cookies.items():
        foo.append(k + '=' + v + '; ')
    bar: str = "".join(foo)
    with open(COOKIES_PATH, 'w') as f:
        f.write(bar)

具体调用如下:

# login.yaml

name: login
base_url: http://xxxxxxx

request:
  method: POST
  url: /login
  data:
    uid: xxx
    password: xxx

teardown_hooks:
  - ${teardown_saveCookies($response)}


# other api or testcase

name: other api
base_url: http://xxxxxxx

request:
  method: GET
  url: /others
  headers:
    Cookie: ${generate_cookies()}

token

同理,token 的保存和读取也大同小异:

import time
import json
import requests
from httprunner.api import HttpRunner

AUTHORIZATION_PATH = r'xxx/xxx/authorization'

def generate_authorization():
    if (not os.path.exists(AUTHORIZATION_PATH)) or (
            3600 < int(time.time()) - int(
        os.path.getctime(AUTHORIZATION_PATH))):
        # authorization 文件不存在或最后修改时间超过 3600 秒(1 个小时)则重新登录
        runner = HttpRunner()
        runner.run(r'api/login.yaml')
    with open(AUTHORIZATION_PATH, 'r') as f:
        authorization: str = f.read()
    return authorization

def teardown_saveAuthorization(response: requests.Response):
    foo: dict = json.loads(response.text)
    bar: str = "Bearer " + foo['data']['token']
    # 保存 authorization 到文件给其他 api 调用
    with open(AUTHORIZATION_PATH, 'w') as f:
        f.write(bar)

这里生成 cookies 和 token 直接用的是 httprunner 的 api ,当然也可以直接使用 requests 拼装登录授权的接口来获取 cookies 或 token。


-事必有法,然后有成- 最后祝大家早日达到测试的天花板!



 以下是我收集到的比较好的学习教程资源,虽然不是什么很值钱的东西,如果你刚好需要,可以评论区,留言【777】直接拿走就好了

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何设计一个高并发系统?

其实所谓的高并发&#xff0c;如果你要理解这个问题呢&#xff0c;其实就得从高并发的根源出发&#xff0c;为啥会有高并 发&#xff1f;为啥高并发就很牛逼&#xff1f; 浅显一点&#xff0c;很简单&#xff0c;就是因为刚开始系统都是连接数据库的&#xff0c;但是要知道数据…

关于英语翻译中的归化与异化,你可以了解一下

据了解&#xff0c;归化和异化是翻译中使用的两种不同手段&#xff0c;它们都能在目的语文化中完成各自的使命&#xff0c;都有其存在的价值。那么&#xff0c;究竟什么是归化&#xff0c;什么是异化&#xff1f;英语翻译中的归化与异化有什么特征&#xff1f; 归化是让作者靠近…

Rust 基础入门 —— 字符、布尔、单元 类型

字符、布尔、单元 类型 字符类型&#xff08;char&#xff09; 对于字符类型我们有更大的自由性&#xff0c;概括一下&#xff1a; 更大的编码范围&#xff0c;让rust 可以展示更多的内容。统一的字节空间&#xff0c;字符也是四个字节的内存大小。严格区分的 "" …

reduceByKey 和 groupByKey 的分析与区别

reduceByKey 源码 def reduceByKey(partitioner: Partitioner, func: (V, V) > V): RDD[(K, V)] self.withScope {combineByKeyWithClassTag[V]((v: V) > v, func, func, partitioner)}/*** Merge the values for each key using an associative and commutative reduce…

保姆级教程:带你体验华为云测试计划CodeArts TestPlan

华为云测试计划&#xff08;CodeArts TestPlan&#xff09;是面向软件开发者提供的一站式云端测试平台&#xff0c;覆盖测试管理、接口测试&#xff0c;融入DevOps敏捷测试理念&#xff0c;帮助您高效管理测试活动&#xff0c;保障产品高质量交付。 登录华为云账号&#xff1a…

使用JMeter安装RabbitMQ测试插件的步骤

整体流程如下&#xff1a;先下载AMQP插件源码&#xff0c;可以通过antivy在本地编译成jar包&#xff0c;再将jar包导入JMeter目录下&#xff0c;重启JMeter生效。 Apache Ant 是一个基于 Java 的构建工具。Ant 可用于自动化构建和部署 Java 应用程序&#xff0c;使开发人员更轻…

【2023年江西省研究生数学建模竞赛】题目一 蒸汽发生器倒U型管内液体流动 建模方案及参考文献

代码与结果如下&#xff1a;完整文档见文末 完整思路”请点击这里“到原文章获取 题目&#xff1a; PACTEL压水堆整体测试设备在2009年建造&#xff0c;用于带有垂直倒U型管蒸汽发生器的压水堆热液压相关的安全性研究,参见图1。 PACTEL压水堆设施包括一个反应堆压力容器模型…

Redis如何统计一个亿的keys?

前言 不知你大规模的用过Redis吗&#xff1f;还是仅仅作为缓存的工具了&#xff1f;在Redis中使用最多的就是集合了&#xff0c;举个例子&#xff0c;如下场景&#xff1a; 签到系统中&#xff0c;一天对应一系列的用户签到记录。 电商系统中&#xff0c;一个商品对应一系列的…

ARM-SWI 和未定义指令异常中断处理程序的返回(七)

文章目录 处理流程示例代码实现SWI未定义指令 附录源码 处理流程 SWI 和未定义指令异常中断是由当前执行的指令自身产生的&#xff0c;当 SWI 和未定义指令异常中断产生时&#xff0c;程序计数器的 PC 的值还未更新&#xff0c;它指向当前指令后面第 2 条指令&#xff08;对于…

Git的常见操作

Git版本控制 开发难题 在实际开发中我们会遇到一些问题&#xff0c;电脑蓝屏&#xff0c;代码丢了&#xff0c;懊悔不&#xff1f; 时间长了&#xff0c;文件找不到了。懊悔不&#xff1f;手欠&#xff0c;之前代码运行好好的&#xff0c;非要去优化下。结果还 不如以前&am…

京东天猫数据查询与分析:2023年厨电细分市场数据分析

随着消费者对生活品质的追求持续提高&#xff0c;我国厨房电器产品的需求也日趋多样化&#xff0c;市场中厨房电器的品类越来越多&#xff0c;我国厨房电器的市场规模也不断扩大。 根据鲸参谋电商数据显示&#xff0c;2023年1月至4月&#xff0c;天猫平台上厨房电器的销量为670…

搭建个人hMailServer 邮件服务实现远程发送邮件

文章目录 1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 转载自cpolar极点云文章&#xff1a;搭建个人hMailServer 邮件服务实现远程发送邮件 hM…

ChatGPT微调系列一:总述 微调 的基本流程

文章目录 前言一、啥叫微调二、为啥要微调三、不是所有模型都可以微调的四、总述微调的基本流程&#xff0c;以及涉及的主要函数&#xff0c;参数1. 安装2. 准备训练数据3. openai.api_key os.getenv() 进行一个说明4. 通过API 调用模型 常用函数5. 微调模型 常用函数6. OpenA…

Maven 使用详细教程

目录 Maven 介绍 Maven 安装 1、安装JDK 2、下载Maven安装文件 3、配置环境变量 4、检测安装成功 Maven 标准工程结构 Maven 版本要素 Maven仓库 1、本地仓库&#xff1a; 2、中央仓库 3、其他远程仓库 创建Maven工程 使用命令方式创建Maven工程 Eclipse中创建…

智能大棚自动控制系统 实现传统农业精细化管理

新型农业经营主体管理系统是指为了适应农村经济发展需求&#xff0c;提高农业生产组织化、规模化、现代化程度&#xff0c;促进农业产业结构调整和农村产业转型升级&#xff0c;推动农村经济社会持续健康发展而建立的一套管理体系。 该系统主要包括农产品生产、种植、养…

JavaWeb学习路线(8)——登录

一、基本登录功能 &#xff08;一&#xff09;需求&#xff1a; 根据账号与密码判别用户是否可以登录 &#xff08;二&#xff09;实现步骤 Controller接收传递的JSON格式数据&#xff0c;使用RequestBody实体类进行接收&#xff0c;调用Service具体处理。Service创建登录接…

循环购应运而生,让老百姓敢于消费、有钱消费、愿意消费

​小编介绍&#xff1a;10年专注商业模式设计及软件开发&#xff0c;擅长企业生态商业模式&#xff0c;商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地&#xff1b;扶持10余个电商平台做到营收过千万&#xff0c;数百个平台达到百万会员&#xff0c;欢迎咨询。 无论…

7 植物背景分离、RGB、HSV特征提取案例(matlab程序)

学习目标&#xff1a;背景分离和RGB等特征提取 1.简述 叶片RGB图像背景精确分离的方法,包括以下图像背景分离方法:S1:选取叶片,所得到的原始图像;S2:采用MATLAB 2016R软件将RGB图像转化为HSV图像,以饱和度0.190.21为界限,将小于界限的图像明度调整为0,并转化为灰度图;S3:用edg…

Redis高并发分布式锁

文章目录 高并发场景秒杀抢购超卖Bug高并发场景秒杀抢购Demo测试结果 JVM级别锁使用nginx对本地服务进行负载均衡 Redis实现分布式锁Redis分布式锁实现DemoRedis分布式锁有关问题 分布式锁性能的提升减少锁的粒度使用异步处理 高并发场景秒杀抢购超卖Bug 在今天的数字化世界中&…

供应商索赔(金税数据)导入并创建凭证(ALV长篇备忘三)

情境/背景:供应商三包索赔款项源起QMS质量系统&#xff0c;联动金税系统完成发票开具&#xff0c;最终在SAP系统中创建完成财务凭证。该流程为手工操作&#xff0c;费时费力且效率低下容易出错。 目标/任务:把QMS供应商三包索赔业务搬上线,同SAP FI顾问梳理功能说明书&#xf…