HttpRunner2.X 版本和 3.X 版本的区别到底有哪些?(吐血总结!)

前言

HttpRunner 的版本截止到目前已经更新到3.1.5了,那么很多初学者都有这样的疑问:
HttpRunner2.X 版本和 3.X 版本的区别到底有哪些?
到底要不要学2.X 版本,还是直接入手3.X 版本呢?

设计理念上的差异

HttpRunner 每一次大版本的更新,都会有设计理念上的大的改变,可以从官方文档上了解到.

HttpRunner 2.X

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

  • 充分复用优秀的开源项目,不追求重复造轮子,而是将强大的轮子组装成战车
  • 遵循 约定大于配置 的准则,在框架功能中融入自动化测试最佳工程实践
  • 追求投入产出比,一份投入即可实现多种测试需求

从 2.0 版本开始,HttpRunner 采用了分层机制,同时,强调如下几点核心概念:

  • 测试用例(testcase)应该是完整且独立的,每条测试用例应该是都可以独立运行的
  • 测试用例是测试步骤(teststep)的 有序 集合,每一个测试步骤对应一个 API 的请求描述
  • 测试用例集(testsuite)是测试用例的 无序 集合,集合中的测试用例应该都是相互独立,不存在先后依赖关系的;如果确实存在先后依赖关系,那就需要在测试用例中完成依赖的处理

2.X 版本的亮点功能在于用例的分层机制,重复的接口请求可以写到单独API层,用例去调用API,层级结构非常清晰,每个层级做好自己的事情。

HttpRunner 3.X

HttpRunner v3.x 支持3种用例格式:pytest、YAML和JSON。
设计理念

  • 约定优于配置
  • 投入产出比很重要
  • 拥抱开源,依赖requests ,pytest ,pydantic ,allure 和 locust

pytest、YAML和JSON格式的测试用例完全等价,包含的信息内容也完全相同。

  • 对于有python基础的,建议以pytest格式而不是以前的YAML / JSON格式编写和维护测试用例。
  • 对于新手来说,推荐使用 JSON 格式,虽然描述形式上稍显累赘,但是不容易出错(大多编辑器都具有 JSON 格式的检测功能);
    同时,HttpRunner 也内置了 JSON 格式正确性检测和样式美化功能,详情可查看《Validate & Prettify》 。
  • 对于熟悉 YAML 格式的人来说,编写维护 YAML 格式的测试用例会更简洁,但前提是要保证 YAML 格式没有语法错误。

HttpRunner v3.x开始,HttpRunner 作者建议大家回到代码上,鼓励大家去写python代码了(可能认为代码还是很重要),用pycharm等编辑器可以自动补齐语法,编写效率更高。
对于有一些代码基础的同学来说,还是很高效的,毕竟还是有很多小伙伴不习惯与yaml格式,总是在语法上犯错,导致编写脚本效率很低。

对比差异

2.x 版本和3.x版本功能上对比差异

功能点 HttpRunner 2.X HttpRunner 3.X
python用例框架 unittest pytest(v5.4.3)
录制.har har2case支持 har2case支持
用例文件格式 YAML/JSON YAML/JSON/Pytest
HTTP(S)请求库 requests requests
用例分层 三层:API/TestCase/TestSuite 弱化了API层,去掉分层机制
参数化parameters 2.x版本在TestSuites层实现,TestCase不支持 3.x版本TestCase中实现
extract提取变量 支持content.x.x格式/re正则/jsonpath 只支持jmespath表达式
返回html格式 re正则提取 不支持re正则提取
文件上传 upload关键字支持 upload关键字支持
validate校验 comparator 校验一样 comparator 校验一样
comparator 支持debugytalk.py 自定义 不支持自定义
hook机制 支持 支持
debugtalk.py辅助函数 支持 支持
测试报告 自带html报告 不自带报告了
extent report 支持 不支持
Allure 不支持 支持
Locust 支持 支持
CLI命令行运行 支持 支持
学习难度 低难度 偏中高级
稳定性 偏中
作者版本维护 不维护 继续维护

底层框架区别

HttpRunner 2.X 是基于 Python 的 Unittest 框架运行用例,
HttpRunner 3.X 是基于 Python 的 Pytest 框架运行用例,支持了 Pytest 框架,运行用例性能会得到很大的提升。
既然支持了 Pytest,意味着 Pytest 的一些插件都可以用了,比如 Allure 插件,也可以在 conftest 中写一些钩子函数,自己开发插件了,扩展性得到很大的提升!

用例格式区别

HttpRunner 2.X 支持yaml 和 json格式,json和yaml是可以互相转换,以yaml为例

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

config:
    name: logincase
    variables: {}
teststeps:
-
    name: login case1
    request:
        url: http://127.0.0.1:8000/api/v1/login/
        method: POST
        headers:
            Content-Type: application/json
            User-Agent: python-requests/2.18.4
        json:
            username: test
            password: 123456
    validate:
        - eq: [status_code, 200]
        - eq: [headers.Content-Type, application/json]
        - eq: [content.msg, login success!]
        - eq: [content.code, 0]

HttpRunner 3.x 除了支持yaml和json格式,还可以支持pytest格式用例。
yaml格式跟2.x版本是一样的,可以直接运行上面的yaml格式,会生成一个pytest格式用例

# NOTE: Generated By HttpRunner v3.1.5
# FROM: testcaselogin.yml
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

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


class TestCaseLogin(HttpRunner):

    config = Config("logincase")

    teststeps = [
        Step(
            RunRequest("login case1")
            .post("http://127.0.0.1:8000/api/v1/login")
            .with_json({"username": "test", "password": "123456"})
            .validate()
            .assert_equal("status_code", 200)
            .assert_equal("body.msg", "login success!")
            .assert_equal("body.code", 0)
            .assert_equal("body.username", "test")
            .assert_length_equal("body.token", 40)
        ),
    ]


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

extract 提取与validate校验

HttpRunner 3.x 只支持 jmespath 提取接口返回的json数据格式,jmespath是类似于jsonpath的提取表达式
jmespath 提取示例,访问/api/test/demo接口,接口返回如下

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

{
    "code":0,
    "msg":"成功success!",
    "data":[
        {
            "age":20,
            "create_time":"2019-09-15",
            "id":1,
            "mail":"283340479@qq.com",
            "name":"yoyo",
            "sex":"M"
        },
        {
            "age":21,
            "create_time":"2019-09-16",
            "id":2,
            "mail":"123445@qq.com",
            "name":"yoyo111",
            "sex":"M"
        }
    ]
}

需求:

  • 1.提取code值,校验结果为:0
  • 2.msg值,校验结果:成功success!
  • 3.提取data数据,校验结果长度是:2
  • 4.提取data数据中第一条数据,校验name的值:yoyo
  • 5.提取data数据中name的值为yoyo的邮箱,并校验结果是:283340479@qq.com
  • 6.提取data数据组中,年龄大于20的结果,并校验结果的数量是:1

httprunner3.x 对应的 py 代码

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

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


class TestCaseTestDemo(HttpRunner):

    config = Config("test demo").base_url("http://127.0.0.1:8000")

    teststeps = [
        Step(
            RunRequest("step login")
            .get("/api/test/demo")
            .validate()
            .assert_equal("status_code", 200)
            .assert_equal("body.code", 0)
            .assert_equal("body.msg", "成功success!")
            .assert_equal("body.length(data)", 2)
            .assert_equal("body.data[0].name", "yoyo")
            .assert_equal("body.data[?name=='yoyo'].mail", ["283340479@qq.com"])
            .assert_equal("body.data[?name=='yoyo'].mail|[0]", "283340479@qq.com")
            .assert_equal("body.length(data[?age>`20`])", 1)
        ),
    ]


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

不得不说jmespath在提取json方面是非常强大的,httprunner2.x是可以支持jsonpath表达式的

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

    extract:
        code: $.code
    validate:
        - eq: [status_code, 200]
        - eq: [headers.Content-Type, application/json]
        - eq: [$.code, 0]
        - eq: ["$code", 0]

但是2.5.7版本有个小bug,一直没修复,详情参考https://www.cnblogs.com/yoyoketang/p/14884606.html

返回html提取

httprunner3.x是不支持html解析的,可以看到源码里面此功能还没开发完善.

class StepRequestExtraction(object):
    def __init__(self, step_context: TStep):
        self.__step_context = step_context

    def with_jmespath(self, jmes_path: Text, var_name: Text) -> "StepRequestExtraction":
        self.__step_context.extract[var_name] = jmes_path
        return self

    # def with_regex(self):
    #     # TODO: extract response html with regex
    #     pass
    #
    # def with_jsonpath(self):
    #     # TODO: extract response json with jsonpath
    #     pass

有些接口返回的并不是json格式,如果返回html格式, 那就没法提取了,httprunner2.x 可以支持正则表达式提取,这点还是很好的

config:
    name: logincase
    variables: {}
teststeps:
-
    name: test demo case1
    request:
        url: https://www.cnblogs.com/yoyoketang/
        method: GET
        headers:
            User-Agent: Fiddler
            Content-Type: application/json
        verify: false
    extract:
        title: '<title>(.+?)</title>'
    validate:
        - eq: [status_code, 200]
        - eq: ['<title>(.+?)</title>', 上海-悠悠 - 博客园]

comparator 校验方式

httprunner2.x 和 httprunner3.x 支持的 comparator 校验方式是一样的

comparator 缩写 功能
equal "eq", "equals", "equal" 相等
less_than "lt", "less_than" 小于
less_or_equals "le", "less_or_equals" 小于或等于
greater_than "gt", "greater_than" 大于
greater_or_equals "ge", "greater_or_equals" 大于或等于
not_equal "ne", "not_equal" 不等于
string_equals "str_eq", "string_equals" 转字符串相等
length_equal "len_eq", "length_equal" 长度相等
length_greater_than "len_gt","length_greater_than" 长度大于
length_greater_or_equals "len_ge","length_greater_or_equals" 长度大于或等于
length_less_than "len_lt", "length_less_than" 长度小于
length_less_or_equals ""len_le", "length_less_or_equals" 长度小于或等于
contains check_value 包含 expect_value
contained_by expect_value 包含check_value
type_match type类型匹配
regex_match 正则匹配re.match(expect_value, check_value)
startswith 字符串以xx开头
endswith 字符串以xx结尾

yaml 中可以写2种格式校验

- {"comparator_name": [check_value, expect_value]}
- {"check": check_value, "comparator": comparator_name, "expect": expect_value}

httprunner3.x 并不支持自己定义的校验方式,httprunner2.x可以支持自定义校验,如

# debugtalk.py
# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/


# 获取data数据,断言每个数据的age字段大于等于expect_age
def all_age_great(data, expect_age):
    """ all age great then expect_age
    """
    for info in data:
        assert info.get('age') >= expect_age

于是 yaml 用例可以这样写

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

config:
    name: test_demo
    base_url: http://127.0.0.1:8000
    variables: {}

teststeps:
-
    name: test_demo case1
    request:
        url: /api/test/demo
        method: GET
        headers:
            Content-Type: application/json
            User-Agent: python-requests/2.18.4
    validate:
    -    check: content.data
         comparator: all_age_great
         expect: 18
    -    all_age_great: [content.data, 18]

测试报告差异

httprunner3.x 运行用例是pytest框架,也就是意味着可以支持强大的Allure报告了

httprunner 2.x 运行用例是unittest框架,会自带一个简单的测试报告

也可以支持自己扩展一个extent report报告模板

版本稳定性与学习成本

稳定性:
httprunner2.x 版本更新到2.5.7了,虽然有一些小BUG,整体上还是很稳定的,目前也很多公司在用了,已经有看得到的成果,稳定性较强!
缺点是作者不继续维护2.x版本了
httprunner3.x 版本更新到3.1.5了,最近的一次更新是在2021年6月27,距离上一次更新差不多1年了,版本改动也很小,更新的频率放慢了很多。

学习成本:
httprunner2.x 支持yaml/json格式的用例,意味着我们只需学一个yaml(或json)文件就能写接口自动化了,初学者可以很快的掌握。
httprunner3.x 支持yaml/json/pytest格式的用例,多了一个pytest格式的用例,那么意味着学习成本会增多了,初学者掌握的难度较大,适合之前就已经有学过pytest的同学。

还有其它细节上的区别,就不一一总结了,如果有同学能补充的可以留言!

网易云课程

httprunner 2.x实战教程网易云课程地址


httprunner 2.x实战教程点我 ->立即报名

httprunner 3.x实战教程网易云课程地址


httprunner 3.x实战教程点我 ->立即报名

原文地址:https://www.cnblogs.com/yoyoketang/p/15009395.html