连测试大拿都不敢说熟练掌握的HTTPRUNNER2.x使用技巧

简介: 这篇文章详细介绍了HTTPRunner 2.x的高级使用技巧,包括工具的设计思想、核心功能、分层测试思想,以及如何搭建开发环境、理解基础概念、掌握关键知识点和进行框架扩展使用。

一、HTTPRUNNER2.x

详见HttpRunner2.x 使用手册

1.1、工具介绍
  • HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。
1.2、设计思想
  • 充分复用优秀的框架组装成更强大完整的框架
  • 必须遵循 约定大于配置 的准则,在自动化测试中充分体现
  • 追求投入产出比,一份投入即可实现多种测试需求
1.3、核心功能
  • 继承Requests的全部功能
  • 采用json/yaml格式作为测试用例数据载体
  • 支持debugtalk.py辅助函数,增强脚本实践中的灵活性,实现动态计算逻辑
  • 支持测试用例分层,实现测试用例复用:数据层、业务(逻辑层)层
  • 支持unittest框架的setup、teardown处理机制:hook机制
  • 支持har录制脚本生成测试用例(har2case)
  • 结合locust框架,支持分布式性能测试
  • 支持CLI命令行调用模式,便于jenkins集成
  • 展示层:测试结果统计及优美的HTML报告+日志
  • 扩展性:支持二次开发及实现web平台化
1.4、关于分层测试思想

区分一下自动化测试分层和测试框架分层、项目结构分层

  • 所谓自动化测试分层,根据投入与产出比自上而下:UI(系统测试)、服务(api/集成测试)、底层(单元测试)
  • 测试框架分层,能实现自动化测试的有:接口、UI、性能等;均采用测试数据与脚本分离策略
    • 接口自动化测试框架分层:数据层(测试数据/用例)、业务层(逻辑层)、公共层(业务调用的公共方法)
    • UI自动化测试框架分层(以PO设计模式为例):页面对象层(包含元素定位)、业务逻辑层(调用页面对象)、测试数据层(数据与脚本分离)
  • 实现测试分层后搭建工程结构:业务层(调用或组装测试用例)、数据层(数据与测试用例/脚本分离)、公共库(基础类公共方法)、工具层(日志系统、数据库处理、报告处理)、展示层(HTML报告展示)、持久层(譬如用例、html报告等是否存放数据库)

二、搭建开发环境

我们是测试,为啥叫开发环境?因为测试的所有脚本及数据调试都是在本地开发测试完成,故而叫开发环境。测试环境适用于投产前的测试验证。

2.1、python环境

虽然官方支持了python2和python3,但是在咱们实际开发中,建议还是使用python3且在3.6及以上版本。

2.2、httprunner安装方式

为啥要指定安装版本?因为当前httprunner托管在PyPI上的稳定版已经是3.x版本了。

  • pip install httprunner==2.3.2

版本升级

  • pip install -U HttpRunner

安装校验

  • hrun -V 或者–help
  • har2case -V
2.3、关于python开发环境

实际开发过程中,建议养成良好的开发模式,在不同工程中创建不同的python虚拟开发环境,一则便于管理,二则便于工程迁移

创建虚拟环境的几种方式,有很多:推荐anaconda或者python -m venv

  • python -m venv /path虚拟路径

三、基础概念

建议:在想使用某个工具/框架之前,先理解它的原理/设计思想,再弄明白与之对应理论概念。

  • 测试用例(testcase)、测试步骤(teststep)、测试用例集(testsuite)
    • 测试用例集testsuite下有testcases包含多个testcase
{
    "config": {
        "name": "测试用例集:业务名称",
        "variables": {
            "token": "存放公共变量,可以在testcases下testcase中使用",
        },
        "base_url": "${ENV(URL)}"
    },
    "testcases": [{
            "name": "可以是某个测试用例或api",
            "testcase": "testcases/homeIndex.json"
        },
        {
            "name": "支持组装多个测试用例",
            "testcase": "testcases/myPractiecs.json"
        }
    ]
}
    • 测试用例testcase下有一个或多个test,它又能包含api、testcase;关于teststeps是在har2case转换录制的har文件才有的内容,如下示例:
{
    "config": {
        "name": "可以描述一个业务场景或者单个用例业务",
        "base_url": "https://www.xxx.com"
    },
    "teststeps": [{
        "name": "接口业务名称描述",
        "skip": "skip login",
        "request": {
            "url": "/xx/xx/passwordLogin",
            "method": "POST",
            "headers": {
                "Content-Type": "application/json;charset=UTF-8",
                "User-Agent": "IeltsBroV3/10.0.0 (com.yasiBro.v2; build:5; iOS 13.3.0) Alamofire/4.9.0"
            },
            "json": {
                "password": "111111",
                "deviceid": "99B5D095-67AD-4B79-A995-6C869A895873",
                "mobile": "13800138000",
                "pushToken": "d90e1e770a37ac3464930c968fed9885",
                "deviceName": "iPhone 8 Plus",
                "verifyCode": "",
                "loginType": 0,
                "channel": 0,
                "deviceType": "ios",
                "zone": "86"
            }
        },
        "extract": [{
            "token": "content.content.token"
        }],
        "validate": [{
                "eq": [
                    "status_code",
                    200
                ]
            }
        ]
    }]
}
    • 框架中正常演示的是
[{
        "config": {
            "name": "全局设置.",
            "variables": {
                "user_agent": "存放灵活变量"
            },
            "verify": false
        }
    },
    {
        "test": {
            "name": "调用api拿到响应token",
            "api": "api/login.yml",
            "extract": {
                "token": "content.content.token"
            },
            "validate": [{
                "eq": [
                    "status_code",
                    200
                ]
            }]
        }
    },
    {
        "test": {
            "name": "请求某个业务接口",
            "api": "api/get_status.yml",
            "validate": [{
                "eq": [
                    "status_code",
                    200
                ]
            }]
        }
    }
]
    • api的写法
{
    "name": "登录接口",
    "base_url": "${ENV(URL)}",
    "variables": {
        "expected_status_code": 200
    },
    "request": {
        "url": "/xxx/xxx/passwordLogin",
        "method": "POST",
        "json": {
            "appVersion": 9,
            "channel": 1,
            "deviceName": "HUAWEI EML-AL00",
            "deviceType": "android",
            "deviceid": "0795cd72-3e05-40ba-9733-5df1c1fa0970",
            "loginType": 0,
            "mobile": "${ENV(MOBILE)}",
            "password": "${ENV(PASSWORD)}",
            "pushToken": "25b9b066dc939b9863fe9feb3fca654d",
            "systemVersion": "8.1.0",
            "zone": 86
        }
    },
    "validate": [{
        "eq": [
            "status_code",
            200
        ]
    }]
}

这个框架还是建议使用yaml格式作为测试用例数据载体,看这个括号都眼花缭乱,维护起来也比较麻烦,yaml是一种dict or list的结果,可读性更好!

  • api示例如下(是不是清晰可人):
name: 登录接口
base_url: ${ENV(URL)}
variables:
    expected_status_code: 200
request:
    url: /hcp/apiLogin/passwordLogin
    method: POST
    json:
        appVersion: 9.0
        channel: 1
        deviceName: HUAWEI EML-AL00
        deviceType: android
        deviceid: 0795cd72-3e05-40ba-9733-5df1c1fa0970
        loginType: 0
        mobile: ${ENV(MOBILE)}
        password: ${ENV(PASSWORD)}
        pushToken: 25b9b066dc939b9863fe9feb3fca654d
        systemVersion: 8.1.0
        zone: 86
validate:
    - eq: [status_code, 200]
3.1、快速应用

上面已经对httprunner框架的基础概念有了了解,使用它的特性,就可以快速开展测试工作。

  • 简要说明如何快速使用这个框架吧(文字描述版)
第一步:抓包,charles导出har数据包
第二步:转换,har2case xxx.har 默认json格式,-2y参数表示yaml格式
第三步:执行,hrun xxx.yml ,执行完毕当前目录下生成reports/xxx.html报告
3.2、应该要掌握的知识点
3.2.1、hook机制

测试用例testcase,config新增关键字:setup_hooks、teardown_hooks,表示在测试用例执行前后用于准备或清理工作

  • setup_hooks
  • teardown_hooks
    • 测试用例层testcase
- config:
    name: 基础配置
    request:
        base_url: http://127.0.0.1:8080/
    setup_hooks:
        - ${hook_print(setup)}
    teardown_hooks:
        - ${hook_print(teardown)}
    • 测试步骤层teststep
- test:
    name: 获取请求状态
    request:
        url: /get_status
        method: GET
    teardown_hooks:
        - ${get_status($response)}
    validate:
        - eq: ["status_code", 500]
3.2.2、环境变量

应用场景:除了信息安全方面的考虑,还应该考虑如何切换环境、切换配置,故而需要使用全局或局部变量

  • 该框架中可以在任意目录下新增.env文件(作用于当前执行目录),设置环境变量
ACCOUNT=13800013800
PASSWD=111111
BASEURL=https://www.baidu.com
  • 引用:{ENV(ACCOUNT)}\{ENV(PASSWD)}${ENV(BASEURL)}
3.2.3、数据驱动

这里不再演示,在其他文章或网络都有详细使用说明,只说它支持的方式。

  • 在 YAML/JSON 中直接指定参数列表,借用httprunner使用文档中的例子演示
config:
    name: "demo"

testcases:
    testcase1_name:
        testcase: /path/to/testcase1
        parameters:
        # 如下就是直接的列表形式,如果是字典多列表,参数使用-连接:user_agent-version,参数为嵌套列表的字典
            user_agent: ["iOS/10.1", "iOS/10.2", "iOS/10.3"]

    testcase2_name:
        testcase: /path/to/testcase2
        parameters:
        # 如果是字典多列表,参数使用-连接:user_agent-version,参数为嵌套列表的字典
            user_agent-version: 
                - ["iOS/10.1", "10.1"]
                - ["iOS/10.2", "10.2"]
  • 通过内置的 parameterize(可简写为P)函数引用 CSV 文件
config:
    name: "demo"

testcases:
    testcase1_name:
        testcase: /path/to/testcase1
        parameters:
        # 数据量比较大的时候使用
            user_id: ${P(data/user_id.csv)}
  • 调用 debugtalk.py 中自定义的函数生成参数列表,此方式比较灵活
def get_account(num):
    accounts = []
    for index in range(1, num+1):
        accounts.append(
            {"username": "user%s" % index, "password": str(index) * 6},
        )

    return accounts
    • debugtalk定义的函数在测试用例文件中引用如下${func_name(parameters)}:
config:
    name: "demo"

testcases:
    testcase1_name:
        testcase: /path/to/testcase1
        parameters:
            username-password: ${get_account(10)}
3.2.4、关键字应用

这里引用的包括但不局限用例的组成部分

  • extract提取关键字,提取当前接口响应参数作为下个接口的请求参数,参数关联时使用
  • validate响应断言
  • parameters全局参数
  • setup_hooks、teardown_hooks框架支持的hook机制,它的函数放置在debugtalk中,
  • variables测试步骤中定义的变量,作用域当前文件,但是支持从testsuite覆盖testcase
  • base_url在testcase中path部分可以是完整地址,但是不能在有base_url的情况下
  • api可以在testcase中调用api层的测试用例
  • testcase同api有一样的效果
  • output整个用例输出的参数列表

这里演示的用例文件都是yaml格式为准

api演示示例,包含上面的基本关键字,先写debugtalk函数

def set_up():
    """在config层做准备工作"""
    print("我在config层做准备")

def tear_down():
    """在config层做准备工作"""
    print("我在config层清理数据")

def output_request(request):
    """setup,打印请求参数"""
    print(request)

def output_response(response):
    """teardown,打印响应结果"""
    print(response.text)

再组织api文件,两份:有单个的api及testcase

    • 单个api
name: 登录接口
base_url: 接口请求地址
variables:
    expected_status_code: 200
    mobile: 你的账号
    passwd: 你的密码
request:
    url: /xxx/xxx/passwordLogin
    method: POST
    json:
        appVersion: 9.0
        channel: 1
        deviceName: HUAWEI EML-AL00
        deviceType: android
        deviceid: 0795cd72-3e05-40ba-9733-5df1c1fa0970
        loginType: 0
        mobile: $mobile
        password: $passwd
        pushToken: 25b9b066dc939b9863fe9feb3fca654d
        systemVersion: 8.1.0
        zone: 86
validate:
    - eq: [status_code, $expected_status_code]
    • 测试用例
- config:
    name: "集合关键字使用"
    variables:
        user_agent: 'iOS/10.3'
    verify: False
    setup_hooks: 
        - ${set_up()}
    teardown_hooks:
        - ${tear_down()}
    output:
        - user_agent

- test:
    name: 第一次登录
    api: api/login.yml
    extract: 
        token: content.content.token
    validate:
        - eq: ["status_code", 200]
    output:
        - token

- test:
    name: 第二次登录
    api: api/login.yml
    setup_hooks: 
        - ${output_request($request)}
    teardown_hooks:
        - ${output_response($response)}
    extract: 
        token: content.content.token
    validate:
        - eq: ["status_code", 200]
# output无效
    output:
        - token

执行看结果,控制台 image.png

3.2.4、工程结构

以上涉及的文件在工程结构是:api目录、debugtalk、testcase必须在同级目录;

而在hrun使用手脚架创建的工程结构是分api、testcases、testsuites、.env等,本身独立的api/xxx.yml是可以单独运行的,如何执行testcases层调用到api层呢非得进入testcases才能到且在当前目录有api层?但是为什么testsuites层能调到testcases层再到api层呢?

那么结论就是,在使用共同调用login获取token的testcases,其实是放在testsuite中调用api,然后在传给testcases? 这是错误的,错误的!!!

综上:httprunner框架通过–startproject创建的工程结构是支持api、testcases、testsuites同级调用的,也就是说需要在/根路径<工程>执行testsuites、testcases、api下的yml测试用例文件。

四、httprunner扩展

有时在debugtalk.py中也会使用框架的api类来执行测试用例

  • 执行测试用例,可以是目录也可以是文件,也可以是目录和用例的混合:[“path”,“test_file”]
from httprunner.api import HttpRunner

runner = HttpRunner(
    failfast=True,
    save_tests=True,
    log_level="INFO",
    log_file="test.log"
)
summary = runner.run(path_or_tests)
  • 也可以通过调用api生成测试报告,因为响应结果中有html报告中用到的元素
from httprunner import report

report_path = report.gen_html_report(
    summary,
    report_template="/path/to/custom_report_template",
    report_dir="/path/to/reports_dir",
    report_file="/path/to/report_file_path"
)
相关文章
|
4月前
|
人工智能 前端开发 Java
软件测试/人工智能|熟练使用web控件定位技巧,提升测试工作效率!
软件测试/人工智能|熟练使用web控件定位技巧,提升测试工作效率!
211 1
|
6天前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
34 7
Jmeter实现WebSocket协议的接口测试方法
|
6天前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
27 3
快速上手|HTTP 接口功能自动化测试
|
6天前
|
JavaScript 前端开发 测试技术
ChatGPT与接口测试
ChatGPT与接口测试,测试通过
19 5
|
22天前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
25天前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
25天前
|
SQL Java 测试技术
SpringBoot单元测试快速写法问题之PorkService 接口中的 getPork 方法的作用如何解决
SpringBoot单元测试快速写法问题之PorkService 接口中的 getPork 方法的作用如何解决
|
2月前
|
存储
Postman 接口测试配置 Pre-request Script
Postman 接口测试配置 Pre-request Script
107 5
Postman 接口测试配置 Pre-request Script
|
27天前
|
XML Web App开发 数据挖掘
Postman接口测试工具全解析:功能、脚本编写及优缺点探讨
文章详细分析了Postman接口测试工具的功能、脚本编写、使用场景以及优缺点,强调了其在接口自动化测试中的强大能力,同时指出了其在性能分析方面的不足,并建议根据项目需求和个人偏好选择合适的接口测试工具。
31 1