连测试大拿都不敢说熟练掌握的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"
)
相关文章
|
6月前
|
人工智能 前端开发 Java
软件测试/人工智能|熟练使用web控件定位技巧,提升测试工作效率!
软件测试/人工智能|熟练使用web控件定位技巧,提升测试工作效率!
|
7天前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
36 3
|
1月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
58 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
2月前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
238 7
Jmeter实现WebSocket协议的接口测试方法
|
2月前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
247 3
快速上手|HTTP 接口功能自动化测试
|
1月前
|
JavaScript 前端开发 API
vue尚品汇商城项目-day02【9.Home组件拆分+10.postman测试接口】
vue尚品汇商城项目-day02【9.Home组件拆分+10.postman测试接口】
40 0
|
2月前
|
JavaScript 前端开发 测试技术
ChatGPT与接口测试
ChatGPT与接口测试,测试通过
48 5
|
3月前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
4月前
|
存储
Postman 接口测试配置 Pre-request Script
Postman 接口测试配置 Pre-request Script
210 5
Postman 接口测试配置 Pre-request Script

热门文章

最新文章