在 HttpRunner v4.0 全新发布 中我们有介绍过,HttpRunner v4.0 期望成为一款专业级的一体化 API 测试工具,特别是针对性能测试能力进行了重大升级。相比于之前的版本,HttpRunner v4.0 在性能测试部分最大的优化包括如下 4 个方面:
涉及的内容比较多,因此我们针对 HttpRunner v4.0 的性能测试能力规划了一系列专题文章,包括性能测试工具使用、多机负载分布式加压、监控配置、benchmark 数据比对、竞品工具对比、原理解析等等。
本文作为性能测试专题的第一篇文章,将结合一个简单的案例整体介绍如何使用 HttpRunner v4.0 开展性能测试,帮助大家快速上手使用工具。
为了方便大家理解,本文挑选了一个非常简单的案例场景,但同时会尽量多地覆盖常用的性能测试特性。
案例设计如下:
接下来,我们将对这些特性进行具体介绍,并对使用方法进行演示说明。
在性能测试之前,我们需要先准备好性能测试用例。在 HttpRunner 中,得益于「一体化」的特性优势,我们可以在无需对已有接口测试用例做任何修改的情况下,直接运行性能测试。
针对本文中的案例,接口测试用例如下所示:
config:
name: load test demo
variables:
app_version: v1
user_agent: iOS/10.3
base_url: 'http://httpbin.org'
verify: false
teststeps:
- name: get with params
request:
method: GET
url: /get
headers:
User-Agent: '$user_agent/$app_version'
validate:
- check: status_code
assert: equals
expect: 200
msg: check status code
- name: post with params
request:
method: POST
url: /post
headers:
User-Agent: '$user_agent/$app_version'
validate:
- check: status_code
assert: equals
expect: 200
msg: check status code
- name: post with params 2
request:
method: POST
url: /post
headers:
User-Agent: '$user_agent/$app_version'
validate:
- check: status_code
assert: equals
expect: 200
msg: check status code
我们只需将测试命令从 hrp run
改为 hrp boom
,即可启动性能测试,具体的参数配置后面会详细介绍。
需要说明的是:
事务可以将多个接口的测试结果进行聚合统计,性能指标更加贴合真实业务场景。
事务的数据结构如下:
type Transaction struct {
Name string `json:"name" yaml:"name"` // 事务名称,可定义为任意字符串
Type transactionType `json:"type" yaml:"type"` // 事务类型,仅包括 2 种类型,start(事务开始)和 end(结束事务)
}
事务使用示例:
config:
...
teststeps:
...
- name: transaction 1 start
transaction:
name: tran1
type: start
...
- name: transaction 1 end
transaction:
name: tran1
type: end
...
针对「事务」机制,有 2 个需要特别注意的点:
集合点可以确保指定的虚拟用户在同一时刻发起请求,实现类似” 秒杀 “的真实业务场景。
集合点的数据结构如下:
type Rendezvous struct {
Name string `json:"name" yaml:"name"`
Percent float32 `json:"percent,omitempty" yaml:"percent,omitempty"`
Number int64 `json:"number,omitempty" yaml:"number,omitempty"`
Timeout int64 `json:"timeout,omitempty" yaml:"timeout,omitempty"`
}
集合点数据结构参数说明如下:
集合点使用示例:
config:
...
teststeps:
...
- name: rendezvous 1
rendezvous:
name: rendezvous1
number: 50
timeout: 3000
...
- name: rendezvous 2
rendezvous:
name: rendezvous2
percent: 0.8
timeout: 3000
...
针对「集合点」机制,有 2 个需要特别注意的点:
可以看出,HttpRunner v4.0 的「集合点」机制也跟 LoadRunner 保持了一致,功能特性和参数配置方法完全相同。
思考时间可以模拟用户在不同操作间的停顿时间,最大程度还原用户真实的操作行为。
思考时间的数据结构如下:
type ThinkTimeConfig struct {
Strategy thinkTimeStrategy `json:"strategy,omitempty" yaml:"strategy,omitempty"`
Setting interface{} `json:"setting,omitempty" yaml:"setting,omitempty"`
Limit float64 `json:"limit,omitempty" yaml:"limit,omitempty"`
}
type ThinkTime struct {
Time float64 `json:"time" yaml:"time"`
}
其中,ThinkTimeConfig
作为「思考时间」的整体策略,需要在测试用例的 Config
中配置,参数说明如下:
ThinkTime
作为具体步骤间的「思考时间」配置,以单独的 step 存在,参数说明如下:
思考时间使用示例如下:
config:
...
think_time:
strategy: random_percentage
setting:
min_percentage: 1
max_percentage: 1.5
limit: 4
...
teststeps:
...
- name: think time 1
think_time:
time: 2
...
- name: think time 2
think_time:
time: 3
...
在该示例中,思考时间策略为随机比例(random_percentage
),介于 100% ~ 150% 之间;limit 设置为 4s。经过换算,测试步骤中的 think time 1
的最终值在 [2, 3] s 之间,think time 2
的最终值在 [3, 4] s 之间。
经过对已有的接口测试用例进行增强,我们获得了包含「事务」、「集合点」、「思考时间」机制的性能测试用例。
YAML 用例格式的示例如下所示:
config:
name: load test demo
variables:
app_version: v1
user_agent: iOS/10.3
base_url: 'http://httpbin.org'
think_time:
strategy: random_percentage
setting:
min_percentage: 1
max_percentage: 1.5
limit: 2
verify: false
teststeps:
- name: transaction 1 start
transaction:
name: tran1
type: start
- name: get with params
request:
method: GET
url: /get
headers:
User-Agent: '$user_agent,$app_version'
validate:
- check: status_code
assert: equals
expect: 200
msg: check status code
- name: transaction 1 end
transaction:
name: tran1
type: end
- name: think time 1
think_time:
time: 1.5
- name: post with params
request:
method: POST
url: /post
headers:
User-Agent: '$user_agent,$app_version'
validate:
- check: status_code
assert: equals
expect: 200
msg: check status code
- name: rendezvous 1
rendezvous:
name: rendezvous1
percent: 0.8
timeout: 3000
- name: post with params 2
request:
method: POST
url: /post
headers:
User-Agent: '$user_agent,$app_version'
validate:
- check: status_code
assert: equals
expect: 200
msg: check status code
对应的 GoTest 用例格式示例如下:
package tests
import (
"testing"
"time"
"github.com/httprunner/httprunner/v4/hrp"
)
func TestLoadTestDemo(t *testing.T) {
testcase1 := &hrp.TestCase{
Config: hrp.NewConfig("Load Test Demo").
SetBaseURL("http://httpbin.org").
SetThinkTime(
"random_percentage",
map[string]float64{"min_percentage": 1, "max_percentage": 1.5},
4),
TestSteps: []hrp.IStep{
hrp.NewStep("transation 1 start").
StartTransaction("trans1"),
hrp.NewStep("headers").
GET("/headers").
Validate().
AssertEqual("status_code", 200, "check status code").
AssertEqual("headers.\"Content-Type\"", "application/json", "check http response Content-Type"),
hrp.NewStep("transation 1 end").
EndTransaction("trans1"),
hrp.NewStep("think time1").
SetThinkTime(3),
hrp.NewStep("user-agent").
GET("/user-agent").
Validate().
AssertEqual("status_code", 200, "check status code").
AssertEqual("headers.\"Content-Type\"", "application/json", "check http response Content-Type"),
hrp.NewStep("rendezvous 1").
SetRendezvous("rend1").
WithUserPercent(0.8).
WithTimeout(3000),
hrp.NewStep("TestCaseRef").
CallRefCase(&hrp.TestCase{Config: hrp.NewConfig("TestCase2")}),
},
}
b := hrp.NewStandaloneBoomer(1000, 100) //spawn_count: 1000, spawn_rate: 100
go b.Run(testcase1)
time.Sleep(1000 * time.Second) //expected running time
b.Quit()
}
准备好性能测试用例后,我们就可以开始执行性能测试了。
当前 HttpRunner v4.0 支持多种性能测试策略,我们可以在命令行参数中进行指定。
关于性能测试的参数信息,可以通过 hrp boom -h
进行查看。
$ hrp boom --help
run yaml/json testcase files for load test
Usage:
hrp boom [flags]
Examples:
$ hrp boom demo.json # run specified json testcase file
$ hrp boom demo.yaml # run specified yaml testcase file
$ hrp boom examples/ # run testcases in specified folder
Flags:
--cpu-profile string Enable CPU profiling.
--cpu-profile-duration duration CPU profile duration. (default 30s)
--disable-compression Disable compression
--disable-console-output Disable console output.
--disable-keepalive Disable keepalive
-h, --help help for boom
--loop-count int The specify running cycles for load testing (default -1)
--max-rps int Max RPS that boomer can generate, disabled by default.
--mem-profile string Enable memory profiling.
--mem-profile-duration duration Memory profile duration. (default 30s)
--prometheus-gateway string Prometheus Pushgateway url.
--request-increase-rate string Request increase rate, disabled by default. (default "-1")
--spawn-count int The number of users to spawn for load testing (default 1)
--spawn-rate float The rate for spawning users (default 1)
Global Flags:
--log-json set log to json format
-l, --log-level string set log level (default "INFO")
如果你之前使用过 Locust/Boomer,你会发现参数名称很眼熟。是的,我们直接复用了 Locust/Boomer 的参数名称,虽然底层实现进行了比较大的改造,但用法基本保持了一致,你可以对比查看下 Boomer 的参数文档。
参数看上去比较多,接下来对其按照用途进行分组介绍。
性能测试需要指定并发用户数,同时在很多时候我们需要按照阶梯加压的方式初始化并发用户。这里就需要使用到 --spawn-count
和 --spawn-rate
两个参数了。
具体示例如下所示:
$ hrp boom testcase.yml --spawn-count 1000 --spawn-rate 100
在该示例中,我们指定了 1000 并发用户,按照每秒 100 个的速率初始化用户,预计在 10s 后可完成初始化。
在这种模式下,性能测试不会自动结束(后面我们会再新增支持指定压测时长的参数);当我们期望结束压测时,可以通过 kill 命令杀死进程,或者 ctrl+c
来结束性能测试,结束时终端会打印整体测试数据。
有时我们需要在性能测试时对发压流量进行限流,例如期望设置最大 RPS,或者在初始化并发用户时限定增加数率。这就需要使用到 --max-rps
和 --request-increase-rate
。
具体示例如下所示:
$ hrp boom testcase.yml --spawn-count 100 --spawn-rate 100 --max-rps 1000 --request-increase-rate 100
在该示例中,我们指定了 100 并发用户,按照每秒 100 个的速率初始化用户,预计在 1s 后可完成初始化。同时,我们限制在整个压测过程中,hrp 最高只能发压 1000 RPS,同时限定每秒增加的速率为 100 RPS。
如果你对这块儿感到比较懵,没有关系,你暂时只需要知道这里使用了「令牌桶」的算法对发压流量实现了限流处理。后面我们会专门写一篇文章详细介绍这部分的使用方法和机制原理。
除了手动控制压测时长外,HttpRunner v4.0 还支持按照指定的循环次数执行压测,可通过 --loop-count
参数进行指定。
需要说明的是,HttpRunner v4.0 执行循环次数的逻辑参考的是 JMeter,所有虚拟用户均会运行指定的循环次数,即当次压测的整体运行次数为:spawn-count * loop-count
。
执行如下命令,执行完指定循环次数后,HttpRunner 将结束运行并打印整体测试数据。
$ hrp boom testcase.yml --spawn-count 100 --spawn-rate 10 --loop-count 1000
在该示例中,我们指定了 100 个并发用户,每个用户循序运行 1000 次,预计总共运行 100*1000=10w 次。
配置好命令行参数后,即可开始执行性能测试。在性能测试过程中,我们可以通过两种方式查看到性能测试结果数据。
性能测试过程中,hrp 每隔 3s 会打印一次性能数据,其中汇总了 3s 内的所有请求情况。结果样式如下:
Current time: 2022/05/16 03:33:26, Users: 1000, State: running, Total RPS: 533.7, Total Average Response Time: 436.8ms, Total Fail Ratio: 0.0%
Accumulated Transactions: 16176 Passed, 3 Failed
+--------------+--------------------+------------+---------+--------+---------+------+-------+--------------+------------+-------------+
| TYPE | NAME | # REQUESTS | # FAILS | MEDIAN | AVERAGE | MIN | MAX | CONTENT SIZE | # REQS/SEC | # FAILS/SEC |
+--------------+--------------------+------------+---------+--------+---------+------+-------+--------------+------------+-------------+
| request-GET | get with params | 799 | 0 | 320 | 432.20 | 273 | 1854 | 266 | 266.33 | 0.00 |
| request-POST | post with params | 156 | 0 | 280 | 388.44 | 272 | 3633 | 358 | 52.00 | 0.00 |
| request-POST | post with params 2 | 799 | 1 | 400 | 594.02 | 275 | 30000 | 357 | 266.33 | 0.33 |
| transaction | tran1 | 799 | 0 | 320 | 432.37 | 273 | 1854 | 0 | 266.33 | 0.00 |
| transaction | Action | 799 | 1 | 4100 | 4939.17 | 3198 | 35450 | 0 | 266.33 | 0.33 |
+--------------+--------------------+------------+---------+--------+---------+------+-------+--------------+------------+-------------+
针对打印的指标说明如下:
指标名称 | 指标说明 |
---|---|
Users | 当前虚拟用户数 |
State | HttpRunner 当前运行状态 |
Total RPS | 总 RPS |
Total Response | 总响应时间 |
Total Fail Ratio | 总请求错误率 |
Accumulated Transactions | 事务总通过/失败数,包含 Action 事务 |
TYPE | 请求类型 |
NAME | 请求名称 |
REQUESTS | 请求数 |
FAILS | 请求失败数 |
MEDIAN | 响应时间中位数 |
AVERAGE | 响应时间平均值 |
MIN | 响应时间最小值 |
MAX | 响应时间最大值 |
CONTENT SIZE | 响应内容大小 |
REQS/SEC | 每秒请求数 |
FAILS/SEC | 每秒请求失败数 |
注:表格内皆为统计间隔 (3s) 内的性能指标数据
完成性能测试时,会打印整体测试数据,结果样式如下:
=========================================== Statistics Summary ==========================================
Current time: 2022/05/16 03:33:38, Users: 1000, Duration: 57s, Accumulated Transactions: 20947 Passed, 3 Failed
+-------+------------+---------+--------+---------+-----+-------+--------------+------------+-------------+
| NAME | # REQUESTS | # FAILS | MEDIAN | AVERAGE | MIN | MAX | CONTENT SIZE | # REQS/SEC | # FAILS/SEC |
+-------+------------+---------+--------+---------+-----+-------+--------------+------------+-------------+
| Total | 31182 | 2 | 300 | 436.70 | 268 | 30003 | 325 | 547.05 | 0.04 |
+-------+------------+---------+--------+---------+-----+-------+--------------+------------+-------------+
Statistics Summary
展示的是性能测试整个过程中的总体指标数据;指标说明与上面表格一致,只额外增加了一个指标。
指标名称 | 指标说明 |
---|---|
Duration | 测试持续时间 |
除了在终端中查看性能测试过程和结果汇总数据之外,我们还可以通过配置 Prometheus + Grafana 看板,实现 Web 化的实时监控指标展示。
效果如下所示:
限于篇幅,关于 Prometheus + Grafana 的性能监控配置方面的内容,将在下一篇文章《如何使用 HttpRunner v4.0 开展性能监控》中详细进行介绍。
通过以上示例,我们使用 HttpRunner v4.0 完成了一次性能测试操作实践,相信大家应该对 HttpRunner v4.0 的性能测试使用方法有了一个整体的认识。
欢迎大家多多实践,如果在使用过程中遇到任何问题,欢迎通过各种渠道进行反馈,我们将及时进行跟进和解答,并基于大家的反馈进行迭代优化。
接下来,我们将连载介绍 HttpRunner v4.0 的更多性能测试功能特性,敬请期待。
本文作者:xucong053,HttpRunner 核心开发者,重点建设了性能测试相关能力
HttpRunner 项目官网: https://httprunner.com/
如果 HttpRunner 对你有过帮助,麻烦帮忙给个 ⭐️star⭐️ 鼓励下吧
https://github.com/httprunner/httprunner