文章目录


前言

一、httprunner是什么

HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,继承request的全部特性,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试、性能测试、线上监控、持续集成等多种测试需求。

1.httprunner的优点

<1>、在charles或者其他抓包工具中,保存的har文件,在httprunner内支持har文件转换成.py文件 或者是优雅的yaml文件

<2>、httprunner内置了loguru日志模块:https://www.jianshu.com/p/5aead7b6a7a9

<3>、httprunner内置了locust模块,支持接口测试同时,又支持了性能测试(locust具体怎么执行,可以参考我的另一篇博客):https://blog.csdn.net/weixin_46457203/article/details/123001840

<4>、httprunner内置了jmespath模块,如果response过多,用jmespath模块取数据会更加的便捷

<5>、可以通过一行命令,快速的生成一个接口测试框架(hrun的脚手架功能)

<6> httprunner内置了pytest框架,使用pytest命令就可以运行httprunner脚本。

二、安装python、Httprunner、allure-pytest

python的安装,这里不过多讲解
第一个是安装httprunner,第二个是安装allure报告

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple httprunner
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple allure-pytest

之后下载allure报告插件:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/2.13.2/
下载以后解压,allure文件的路径配置到环境变量-path里

查看httprunner的版本

httprunner -V

在这里插入图片描述

三、生成脚手架

在pycharm中使用命令:

httprunner startproject  [filename]

1、新建一个项目名为:ERP_Project的工程

在这里插入图片描述
输入完命令,敲回车,会自动生成完整的项目
在这里插入图片描述

2、查看项目的目录层级

在这里插入图片描述

har: har文件夹存放har文件,har文件可以通过charles或者其他抓包工具来获取
reports:存放测试报告
testcases:存放测试用例的文件集(在脚手架生成后,会自动带入两个yaml示例文件)
debugtalk.py: 在这里写入的方法,可以拿到测试用例中调用

四、charles录制har文件,并用httprunner命令转成.py文件

1、录制脚本,导出har文件

我这里录制的是 Gitee上的开源项目:http://erp2.hzb-it.com/

<1> 打开charles,过滤域名
在这里插入图片描述

<2>抓取一条业务用例: 登录—>组织和人员—>职位管理—>新增职位为:测试工程师

在这里插入图片描述

<3>过滤charles的静态文件,导出所有的接口,格式为.har

选择 Sequence——>将被抓取的域名放到 Filter里面

过滤js、css静态文件-选中,右击鼠标,点击clear(如果没有,就忽略)
在这里插入图片描述

选中,点击clear
在这里插入图片描述

<4>选中所有的文件,选择导出har文件
在这里插入图片描述

选择har文件进行导出
在这里插入图片描述

2、har文件转成.py文件(转成的用例,记得放到testcases文件夹)

将har文件放入脚手架的har目录下
在这里插入图片描述
使用命令,将目标目录har下的ERP_project.har文件转成 py文件

har2case ERP_Project/har/ERP_Project.har

在这里插入图片描述
在当前目录下,就会多出.py文件
在这里插入图片描述

3、har文件转成生成yaml文件

har2case  ERP_Project/har/ERP_Project.har -2y

4、har文件转成生成json文件

har2case ERP_Project/har/ERP_Project.har -2j

五、运行httprunner文件

使用pytest命令运行
方式一:

pytest ERP_Project_test.py

方式二(可打印详细的日志到控制台):

pytest -s ERP_Project_test.py

使用httprunner命令运行

方式一:

六、httprunner内置函数使用

1、httprunner命名规范

  • 类名开头必须是Test
  • 定义的测试类,需要继承httprunner
  • teststeps为测试步骤,每一个测试步骤叫做step
  • step里的RunRequest,是待测的API名字,可按照接口名称填写\
  • .py文件的尾缀,必须是_test

2、httprunner的模块引入

from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

Httprunner:导入Httprunner类,后面的测试类,继承于Httprunner
Config:全局设置,可以设置全局变量,例-variables(**);可以忽略Request库的警告,例-verify(False)
Step:测试步骤,每一个的接口测试用例,对应着一个step
RunRequest:每一个测试步骤的接口名称命名,可以是中文
RunTestCase:每一个测试步骤的接口名称命名,可以是中文。不同于RunRequest的是,RunTestCase只可以用于调用其他hrun文件时使用

3、待测接口命名

在这里插入图片描述

RunRequest("/app/common/login")

命名接口,这里可以写对应的业务接口名称
在这里插入图片描述

比如,我这里命名为:登录

4、设置请求方式

.get,表明这是一个get请求方式的接口
.post,表明这是一个post请求方式的接口
后面需要跟上完整的API路径名
在这里插入图片描述

可通过ctrl+鼠标左击,进入方法内
在这里插入图片描述

httprunner支持:get、post、put、head、delete、options、patch等请求方式

5、.with_headers:headers入参传递

请求接口的headers入参放在这里,在with_headers方法内,需要加上**来读取。
例:

.with_headers(
                **{
                    "Host": "erp2.hzb-it.com",
                    "Content-Length": "27",
                    "Accept": "application/json, text/plain, */*",
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
                    "Content-Type": "application/x-www-form-urlencoded",
                    "Origin": "http://erp2.hzb-it.com",
                    "Referer": "http://erp2.hzb-it.com/",
                    "Accept-Encoding": "gzip, deflate",
                    "Accept-Language": "zh-CN,zh;q=0.9",
                    "Connection": "keep-alive",
                }
            )

在这里插入图片描述

6、config:设置全局化参数

在这里插入图片描述

config = Config("testcase description").verify(False).variables(**{
        "Host":"erp2.hzb-it.com",# todo:定义全局变量
    })

此时定义了一个名为Host的全局变量,整体的httprunner都可以调用
想要定义多个全局变量,也可以在这里设置
在这里插入图片描述

6.1、.base_url():设置全局化项目地址

在这里插入图片描述

7、.with_variables(**{ }):定义局部变量,仅在当前step可用

设置局部变量语法:
1、在RunRequest()后
2、在RunTestCase()后

.with_variables(**{"Content-Length":"27"})

在这里插入图片描述

7.1、引用局部变量

在这里插入图片描述

"Content-Length": "${Content-Length}",

8、${变量}:引用设置的变量

在需要使用的地方,填入:${变量名},就可以引用参数
在这里插入图片描述

这里调用了Host、Accept全局参数

9、.with_cookies:设置cookie值

请求接口的cookies入参放在这里,在with_cookies方法内,需要加上**来读取。
在这里插入图片描述

.with_cookies(
                **{
                    "access-token": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDczNTk0NDEsInVzZXJEZXRhaWxzIjoie1wicm9sZXNcIjpbe1wiY29kZVwiOlwic3VwZXJhZG1pblwiLFwibmFtZVwiOlwi6LaF57qn566h55CG5ZGYXCIsXCJpZFwiOjF9LHtcImNvZGVcIjpcInhpbmd6aGVuZ1wiLFwibmFtZVwiOlwi6KGM5pS_XCIsXCJpZFwiOjExfV0sXCJwYXNzd29yZFwiOlwiJDJhJDEwJE5Fc3JOeUJJUEdFTHg5RHBJYm0veC5Wd0FNT3pobVg0Y09mTzRqendSSmY2WGl6WXJ4akkyXCIsXCJpZGVudGl0eVwiOjEsXCJuYW1lXCI6XCLnrqHnkIblkZhcIixcImlkXCI6MSxcInN0YXRlXCI6MSxcInVzZXJuYW1lXCI6XCJhZG1pblwifSJ9.xLw2cSbOIxQOWhXRgarGcI55U8B353_c0vDS7M-puJ8"
                }
            )

10、with_data:data参数传参

引言:指定HTTP请求正文。这对应于的data参数requests.request

在这里插入图片描述

.with_data({"username": "admin", "password": "123"})

11、with_json:json参数传参

在json中指定HTTP请求正文。这对应于的json参数requests.request。
但要记得在headers声明json传参:{‘Content-Type’:‘application/json;charset=utf8’}

.with_data({"username": "admin", "password": "123"})

在这里插入图片描述

12、extract().with_jmespath():拿到接口的response,用作后续接口使用

httprunner的响应集,整体被命名为:body
我是怎么知道的?可以通过运行hrun,来看下控制台呀
运行命令:pytest ERP_Project_test.py
它的最外面,就是body,所以,我们取值的时候,就要带上body
在这里插入图片描述

12.1 response body怎么取关联接口的响应值?

举例:我想取图中的data参数

extract().with_jmespath("body.data","data")

这样就可以取到参数了。body是最外层,data处于body的下一级,所以用的是body.data
第二个参数是命名取到的变量为:data

12.2 response headers怎么取值?

extract().with_jmespath('headers.Server', 'cookies')

12.3 response cookies怎么取值?

extract().with_jmespath(cookies."key","edit-key")

12.4 怎么确保取的值正确?

运行一遍httprunner:

pytest -s ERP_Project_test.py

在下图,就可以清晰的看到,data参数被取出来了
在这里插入图片描述

12.5 如果response清单返回列表数据,该怎么取值?

可以通过数组下标的方式取值
比如下面,就是取的body下的data下的list下标为0的quantity数据

extract().with_jmespath("body.data.list[0].quantity","quantity")

13、取出的参数,如何运用到其他step中

${变量名}就可以使用,举例

"access-token": "${data}"

在这里插入图片描述

14、.validate():httprunner内置的断言功能

httprunner的断言信息会自动生成:断言响应状态码、断言响应body的文本信息等
.assert_equal():断言文本信息是否相等,也可以自定义断言

比如:取出响应状态码进行断言

.assert_equal("status_code", 200)

取出响应headers参数进行断言

.assert_equal('headers."Content-Type"', "application/json")

取出响应body参数,与预期的匹配的文本信息进行断言

.assert_equal("body.name", "管理员")

.assert_greater_than():断言获取到的值,是否大于预期设定的值

断言取出的值,是否大于20

.assert_greater_than("body.data.totalCount", 20) 

.assert_endswith():断言获取到的值,在字符串末尾是否与预期设定的值一致

断言ss 是否在字符串末尾

.assert_endswith("body.message", "ss")

.assert_startswith():断言获取到的值,在字符串开始是否与预期设定的值一致

断言su 是否在字符串开始

.assert_startswith("body.message", "su")

查看更多的断言方式
按住ctrl+鼠标左键,查看
在这里插入图片描述
在这里插入图片描述

15、RunTestCase、call():业务解耦和调用方法

A文件:ERP_Login_test.py,只有一个login的step

# NOTE: Generated By HttpRunner v3.1.6
# FROM: testcases\ERP_PROJECT.har
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseErpProject(HttpRunner):

    config = Config("testcase description").base_url("http://erp2.hzb-it.com/").verify(False).variables(**{  # todo: .base_url()设置项目全局地址
        "Host":"erp2.hzb-it.com",
        "Accept":"application/json, text/plain, */*" # todo:定义全局变量
    })

    teststeps = [
        Step(
            RunRequest("登录")
            .with_variables(**{"Content-Length":"27"})  #todo:定义局部变量
            .post("app/common/login")
            .with_headers(
                **{
                    "Host": "${Host}",  # todo: 引用Host变量
                    "Content-Length": "${Content-Length}",   # todo:引用局部变量
                    "Accept": "${Accept}",  # todo: 引用Accept变量
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
                    "Content-Type": "application/x-www-form-urlencoded",
                    "Origin": "http://erp2.hzb-it.com",
                    "Referer": "http://erp2.hzb-it.com/",
                    "Accept-Encoding": "gzip, deflate",
                    "Accept-Language": "zh-CN,zh;q=0.9",
                    "Connection": "keep-alive",
                }
            )
            .with_data({"username": "admin", "password": "123"})
            .extract().with_jmespath("body.data","data")
            .validate()
            .assert_equal("status_code", 200)
            .assert_equal('headers."Content-Type"', "application/json;charset=UTF-8")
            .assert_equal("body.msg", "提交成功")
            .assert_equal("body.errCode", 0)
        ),
    ]

if __name__ == "__main__":
    TestCaseErpProject().test_start()

在这里插入图片描述
B文件: ERP_Project_test.py,是登录后的操作,依赖于A文件

RunTestCase()和call()使用语法:

1、RunTestCase()是只有在调用A文件的时候,才可以使用(业务解耦、login解耦等)
2、call():call,调用另一个.py文件的内容。在导入模块时,需要注意,使用别名,不然的话,hrun会识别成两条case

# NOTE: Generated By HttpRunner v3.1.6
# FROM: testcases\ERP_PROJECT.har


from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from ERP_Project.testcases.ERP_Login_test import TestCaseErpProjects as Login

class TestCaseErpProject(HttpRunner):

    config = Config("testcase description").base_url("http://erp2.hzb-it.com/").verify(False).variables(**{  # todo: .base_url()设置项目全局地址
        "Host":"erp2.hzb-it.com",
        "Accept":"application/json, text/plain, */*" # todo:定义全局变量
    })
    teststeps = [
        Step(
            RunTestCase("login")
                .call(Login)
                .export("data")
        ),
        Step(
            RunRequest("/app/common/base/enumList")
                .get("http://erp2.hzb-it.com/app/common/base/enumList")
                .with_headers(
                **{
                    "Host": "erp2.hzb-it.com",
                    "Accept": "application/json, text/plain, */*",
                    "access-token": "${data}",
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
                    "Referer": "http://erp2.hzb-it.com/",
                    "Accept-Encoding": "gzip, deflate",
                    "Accept-Language": "zh-CN,zh;q=0.9",
                    "Cookie": "access-token=${data}",
                    "Connection": "keep-alive",
                }
            )
                .with_cookies(
                **{
                    "access-token": "${data}"
                }
            )
                .validate()
                .assert_equal("status_code", 200)
                .assert_equal('headers."Content-Type"', "application/json")
        ),
    ]
if __name__ == "__main__":
    TestCaseErpProject().test_start()

15.1、如果用例运行报错,如下:

当使用pytest -s xx.py 运行文件时,报错提示
在这里插入图片描述
解决办法:
在运行文件的根目录下,新建一个conftest.py,内容为:

import os

import sys

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__),'..')))

在这里插入图片描述

七、debugtalk.py:辅助函数

debugtalk.py创建小方法,可用于hrun的step中

1、函数的封装

1.1、uuid函数

def get_random_request_id():
    return uuid.uuid4()

1.2、睡眠函数

def sleep(n_secs):
    time.sleep(n_secs)

2、引用函数

引用debugtalk.py文件方法,不需要导入debugtalk.py文件

2.1、.teardown_hook() :退出后调用,teardown方法

.teardown_hook("${sleep(5)}")  #todo:调用debugtalk.py文件方法,执行方法后,等待5s

在这里插入图片描述

八、生成allure报告

hrun ERP_Project_test.py --alluredir=allure   # 生成allure  数据

在这里插入图片描述

allure generate ./allure/ -o ./reports --clean  #  生成allure报告到reports文件夹里

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

九、数据驱动

我先在ERP_Login_test文件中,加了username的全局变量
在这里插入图片描述
导入pytest、hrun的数据驱动模块

import pytest
from httprunner import Parameters

9.1、单组数据驱动

@pytest.mark.parametrize(  # TODO:数据驱动
        'param',
        Parameters({"username": ["admin", "admin1", "admin2"],
                    }
                   ),
    )  # todo: 切换三个账号,执行用例.
    def test_start(self, param):
        super().test_start(param)

因为admin1和admin2不存在这样的账号,所以登录失败了
在这里插入图片描述

9.2、多组数据驱动

我先在ERP_Login_test文件中,加了password的全局变量
在这里插入图片描述

当数据配置多组,会形成笛卡尔积,即3*3,九组测试用例输出

@pytest.mark.parametrize(  # TODO:数据驱动
        'param',
        Parameters({"username": ["admin", "admin1", "admin2"],
                    "password":["123","1234","12345"],# todo:数据配置多组,会形成笛卡尔积,即 3*3,九组测试用例输出
                    }
                   ),
    )  # todo: 切换三个账号,执行用例.
    def test_start(self, param):
        super().test_start(param)

在这里插入图片描述

9.3、引用debugtalk.py写好的方法做数据驱动

在这里插入图片描述

@pytest.mark.parametrize(  # TODO:数据驱动
        'param',
        Parameters({#"username": ["admin", "admin1", "admin2"],
                    "userName": "${get_userName()}",  # todo: 也可以引用debugtalk.py写好的方法去调用
                    "password":["123","1234","12345"],
                    }
                   ),
    )  # todo: 切换三个账号,执行用例.
    def test_start(self, param):
        super().test_start(param)

在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐