HTTP/2

如何测试 HTTP/2 协议

HTTP/2 协议介绍

HTTP/2 相比于 HTTP/1.1,在完全兼容语义的基础上,新增支持了多路复用、二进制分帧、首部压缩、服务端推送等特性,大幅提升了 Web 性能,当前已经进行了较为广泛的应用。

HttpRunner 从 v4.0 开始新增实现了对 HTTP/2 协议的测试支持。

脚本准备

虽然 HTTP/2 协议跟 HTTP/1.1 具有非常大的差异,但从测试脚本的角度,将已有的 HTTP/1.1 脚本升级为 HTTP/2 非常容易,只需要新增一个 http2 描述字段即可;而在请求参数描述、参数关联、结果断言等使用方法方面跟之前的 HTTP/1.1 基本保持了一致。

下面将通过实际的测试用例展示 HTTP/2 脚本的修改方法。

YAML 脚本格式示例

对于 JSON/YAML 形态的测试用例,只需要在 request 对象中添加一个新字段 http2 并且指定为 true

config:
  name: run request with HTTP/2
  base_url: https://postman-echo.com

teststeps:
- name: HTTP/2 get
  request:
    method: GET
    url: "/get"
    http2: true # 只需指定 http2 字段为 true
    params:
      foo1: foo1
      foo2: foo2
    headers:
      User-Agent: HttpRunnerPlus
  validate:
  - check: status_code
    assert: equals
    expect: 200
    msg: check status code
  - check: proto    # 支持对协议类型进行断言
    assert: equals
    expect: HTTP/2.0
    msg: check protocol type
  - check: body.args.foo1
    assert: length_equals
    expect: 4
    msg: check param foo1

另外,HttpRunner v4.0 也新增支持了对协议类型的断言(“check”: “proto”),这对于判断服务端是否支持 HTTP/2 的场景来说是非常实用的,因为有时候服务端不支持 HTTP/2 并且会自动降级为 HTTP/1.1,这时就有必要对协议类型进行断言。

GoTest 脚本格式示例

对于 go test 形态的测试用例,将 HTTP/1.1 升级为 HTTP/2 的方式同样非常简单,只需要在调用链中的 GET、POST 等请求方法之前先调用 HTTP2() 即可。

package tests

import (
   "testing"

   "github.com/httprunner/httprunner/hrp"
)

func TestHTTPProtocol(t *testing.T) {
   testcase := &hrp.TestCase{
      Config: hrp.NewConfig("run request with HTTP/1.1 and HTTP/2").
         SetBaseURL("https://postman-echo.com"),
      TestSteps: []hrp.IStep{
         hrp.NewStep("HTTP/2 get").
            HTTP2().    // 只需新增调用 HTTP2() 方法
            GET("/get").
            WithParams(map[string]interface{}{"foo1": "foo1", "foo2": "foo2"}).
            WithHeaders(map[string]string{"User-Agent": "HttpRunnerPlus"}).
            Validate().
            AssertEqual("status_code", 200, "check status code").
            AssertEqual("proto", "HTTP/2.0", "check protocol type").    // 支持对协议类型进行断言
            AssertLengthEqual("body.args.foo1", 4, "check param foo1"),
         hrp.NewStep("HTTP/2 post").
            HTTP2().
            POST("/post").
            WithHeaders(map[string]string{"User-Agent": "HttpRunnerPlus"}).
            WithBody(map[string]interface{}{"foo1": "foo1", "foo2": "foo2"}).
            Validate().
            AssertEqual("status_code", 200, "check status code").
            AssertEqual("proto", "HTTP/2.0", "check protocol type").
            AssertLengthEqual("body.json.foo1", 4, "check body foo1"),
      },
   }
   err := hrp.NewRunner(t).Run(testcase)
   if err != nil {
      t.Fatalf("run testcase error: %v", err)
   }
}

注意事项

  • 在使用 hrp run 进行接口测试时,通过命令行选项 --proxy-url 设置的代理 URL 对于 HTTP/2 协议的请求不会生效,原因是底层依赖不支持设置代理 URL
  • 在使用 hrp boom 进行性能测试时,通过命令行选项 --disable-keepalive 设置的打开/关闭长连接对于 HTTP/2 协议的请求不会生效,原因是 HTTP/2 协议支持多路复用,天然地达到类似长连接的效果
  • 虽然 RFC 文档中没有强制规定,不过目前大部分 HTTP/2 服务是建立在 SSL/TLS 之上的,因此建议在 URL 中使用 HTTPS