制晚報快訊(記者 李東)今天晚上,北京兩會舉行政務(wù)咨詢。在政務(wù)咨詢上,北京市質(zhì)監(jiān)局副巡視員李亮華介紹,自2017年到2019年,北京市16176臺存在隱患的電梯將得到治理。(法晚微信公號ID:fzwb_52165216)
據(jù)李亮華介紹,2016年,北京市電梯遭投訴、舉報約4200余起,其中,通過12365接到的舉報約一半不屬于安全問題,直接關(guān)系安全問題的舉報約200起。北京老舊電梯約20萬部,其中使用年限超過10年的約占四分之一。
為解決老舊電梯隱患,市質(zhì)監(jiān)相關(guān)部門對電梯存在隱患進(jìn)行了評估,發(fā)現(xiàn)生產(chǎn)于2003年以前的約16176臺電梯存在安全隱患,其中包括9140臺住宅用電梯。
李亮華介紹,自2017年到2019年,北京市將通過暢通住宅專項維修資金、針對電梯的政府救濟(jì)金、探索PPP社會投資等模式進(jìn)行整治。以期達(dá)到更新、改造、停用,或廠家維修保養(yǎng),排除電梯安全隱患。也就是說兩年內(nèi),存在安全隱患的16176臺老舊電梯將得以整治。
HttpRunner v4.0 期望成為一款專業(yè)級的一體化 API 測試工具,特別是針對性能測試能力進(jìn)行了重大升級。相比于之前的版本,HttpRunner v4.0 在性能測試部分最大的優(yōu)化包括如下 4 個方面:
涉及的內(nèi)容比較多,因此我們針對 HttpRunner v4.0 的性能測試能力規(guī)劃了一系列專題文章,包括性能測試工具使用、多機負(fù)載分布式加壓、監(jiān)控配置、benchmark 數(shù)據(jù)比對、競品工具對比、原理解析等等。
本文作為性能測試專題的第一篇文章,將結(jié)合一個簡單的案例整體介紹如何使用 HttpRunner v4.0 開展性能測試,幫助大家快速上手使用工具。
為了方便大家理解,本文挑選了一個非常簡單的案例場景,但同時會盡量多地覆蓋常用的性能測試特性。
案例設(shè)計如下:
接下來,我們將對這些特性進(jìn)行具體介紹,并對使用方法進(jìn)行演示說明。
在性能測試之前,我們需要先準(zhǔn)備好性能測試用例。在 HttpRunner 中,得益于「一體化」的特性優(yōu)勢,我們可以在無需對已有接口測試用例做任何修改的情況下,直接運行性能測試。
針對本文中的案例,接口測試用例如下所示:
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
我們只需將測試命令下達(dá) hrp run 改為 hrp boom,即可啟動性能測試,具體的參數(shù)配置后面會詳細(xì)介紹。
需要說明的是:
事務(wù)可以將多個接口的測試結(jié)果進(jìn)行聚合統(tǒng)計,性能指標(biāo)更加貼合真實業(yè)務(wù)場景。
事務(wù)的數(shù)據(jù)結(jié)構(gòu)如下:
type Transaction struct {
Name string `json:"name" yaml:"name"` // 事務(wù)名稱,可定義為任意字符串
Type transactionType `json:"type" yaml:"type"` // 事務(wù)類型,僅包括 2 種類型,start(事務(wù)開始)和 end(結(jié)束事務(wù))
}
實務(wù)使用示例:
config:
...
teststeps:
...
- name: transaction 1 start
transaction:
name: tran1
type: start
...
- name: transaction 1 end
transaction:
name: tran1
type: end
...
針對「事務(wù)」的機制,有 2 個需要特別注意的點:
集合點可以確保指定的虛擬用戶在同一時刻發(fā)起請求,實現(xiàn)類似” 秒殺 “的真實業(yè)務(wù)場景。
集合點的數(shù)據(jù)結(jié)構(gòu)如下:
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"`
}
集合點數(shù)據(jù)結(jié)構(gòu)參數(shù)說明如下:
集合點使用示例:
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 保持了一致,功能特性和參數(shù)配置方法完全相同。
思考時間可以模擬用戶在不同操作間的停頓時間,最大程度還原用戶真實的操作行為。
思考時間的數(shù)據(jù)結(jié)構(gòu)如下:
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 中配置,參數(shù)說明如下:
ThinkTime 作為具體步驟間的「思考時間」配置,以單獨的 step 存在,參數(shù)說明如下:
思考時間使用示例如下:
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 設(shè)置為 4s。經(jīng)過換算,測試步驟中的 think time 1 的最終值在 [2, 3] s 之間,think time 2 的最終值在 [3, 4] s 之間。
經(jīng)過對已有的接口測試用例進(jìn)行增強,我們獲得了包含「事務(wù)」、「集合點」、「思考時間」機制的性能測試用例。
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
對應(yīng)的 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()
}
準(zhǔn)備好性能測試用例后,我們就可以開始執(zhí)行性能測試了。
當(dāng)前 HttpRunner v4.0 支持多種性能測試策略,我們可以在命令行參數(shù)中進(jìn)行指定。
關(guān)于性能測試的參數(shù)信息,可以通過 hrp boom -h 進(jìn)行查看。
$ 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,你會發(fā)現(xiàn)參數(shù)名稱很眼熟。是的,我們直接復(fù)用了 Locust/Boomer 的參數(shù)名稱,雖然底層實現(xiàn)進(jìn)行了比較大的改造,但用法基本保持了一致,你可以對比查看下 Boomer 的參數(shù)文檔。
參數(shù)看上去比較多,接下來對其按照用途進(jìn)行分組介紹。
性能測試需要指定并發(fā)用戶數(shù),同時在很多時候我們需要按照階梯加壓的方式初始化并發(fā)用戶。這里就需要使用到 --spawn-count 和 --spawn-rate 兩個參數(shù)了。
具體示例如下所示:
$ hrp boom testcase.yml --spawn-count 1000 --spawn-rate 100
在該示例中,我們指定了 1000 并發(fā)用戶,按照每秒 100 個的速率初始化用戶,預(yù)計在 10s 后可完成初始化。
在這種模式下,性能測試不會自動結(jié)束(后面我們會再新增支持指定壓測時長的參數(shù));當(dāng)我們期望結(jié)束壓測時,可以通過 kill 命令殺死進(jìn)程,或者 ctrl+c 來結(jié)束性能測試,結(jié)束時終端會打印整體測試數(shù)據(jù)。
有時我們需要在性能測試時對發(fā)壓流量進(jìn)行限流,例如期望設(shè)置最大 RPS,或者在初始化并發(fā)用戶時限定增加數(shù)率。這就需要使用到 --max-rps 和 --request-increase-rate。
具體示例如下所示:
$ hrp boom testcase.yml --spawn-count 100 --spawn-rate 100 --max-rps 1000 --request-increase-rate 100
在該示例中,我們指定了 100 并發(fā)用戶,按照每秒 100 個的速率初始化用戶,預(yù)計在 1s 后可完成初始化。同時,我們限制在整個壓測過程中,hrp 最高只能發(fā)壓 1000 RPS,同時限定每秒增加的速率為 100 RPS。
如果你對這塊兒感到比較懵,沒有關(guān)系,你暫時只需要知道這里使用了「令牌桶」的算法對發(fā)壓流量實現(xiàn)了限流處理。后面我們會專門寫一篇文章詳細(xì)介紹這部分的使用方法和機制原理。
除了手動控制壓測時長外,HttpRunner v4.0 還支持按照指定的循環(huán)次數(shù)執(zhí)行壓測,可通過 --loop-count 參數(shù)進(jìn)行指定。
需要說明的是,HttpRunner v4.0 執(zhí)行循環(huán)次數(shù)的邏輯參考的是 JMeter,所有虛擬用戶均會運行指定的循環(huán)次數(shù),即當(dāng)次壓測的整體運行次數(shù)為:spawn-count * loop-count。
執(zhí)行如下命令,執(zhí)行完指定循環(huán)次數(shù)后,HttpRunner 將結(jié)束運行并打印整體測試數(shù)據(jù)。
$ hrp boom testcase.yml --spawn-count 100 --spawn-rate 10 --loop-count 1000
在該示例中,我們指定了 100 個并發(fā)用戶,每個用戶循序運行 1000 次,預(yù)計總共運行 100*1000=10w 次。
配置好命令行參數(shù)后,即可開始執(zhí)行性能測試。在性能測試過程中,我們可以通過兩種方式查看到性能測試結(jié)果數(shù)據(jù)。
性能測試過程中,hrp 每隔 3s 會打印一次性能數(shù)據(jù),其中匯總了 3s 內(nèi)的所有請求情況。結(jié)果樣式如下:
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 |
+--------------+--------------------+------------+---------+--------+---------+------+-------+--------------+------------+-------------+
針對打印的指標(biāo)說明如下:
指標(biāo)名稱 | 指標(biāo)說明 |
Users | 當(dāng)前虛擬用戶數(shù) |
State | HttpRunner 當(dāng)前運行狀態(tài) |
Total RPS | 總 RPS |
Total Response | 總響應(yīng)時間 |
Total Fail Ratio | 總請求錯誤率 |
Accumulated Transactions | 事務(wù)總通過/失敗數(shù),包含 Action 事務(wù) |
TYPE | 請求類型 |
NAME | 請求名稱 |
REQUESTS | 請求數(shù) |
FAILS | 請求失敗數(shù) |
MEDIAN | 響應(yīng)時間中位數(shù) |
AVERAGE | 響應(yīng)時間平均值 |
MIN | 響應(yīng)時間最小值 |
MAX | 響應(yīng)時間最大值 |
CONTENT SIZE | 響應(yīng)內(nèi)容大小 |
REQS/SEC | 每秒請求數(shù) |
FAILS/SEC | 每秒請求失敗數(shù) |
注:表格內(nèi)皆為統(tǒng)計間隔 (3s) 內(nèi)的性能指標(biāo)數(shù)據(jù)
完成性能測試時,會打印整體測試數(shù)據(jù),結(jié)果樣式如下:
===========================================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 展示的是性能測試整個過程中的總體指標(biāo)數(shù)據(jù);指標(biāo)說明與上面表格一致,只額外增加了一個指標(biāo)。
指標(biāo)名稱 | 指標(biāo)說明 |
Duration | 測試持續(xù)時間 |
除了在終端中查看性能測試過程和結(jié)果匯總數(shù)據(jù)之外,我們還可以通過配置 Prometheus + Grafana 看板,實現(xiàn) Web 化的實時監(jiān)控指標(biāo)展示。
效果如下所示:
限于篇幅,關(guān)于 Prometheus + Grafana 的性能監(jiān)控配置方面的內(nèi)容,將在下一篇文章《如何使用 HttpRunner v4.0 開展性能監(jiān)控》中詳細(xì)進(jìn)行介紹。
通過以上示例,我們使用 HttpRunner v4.0 完成了一次性能測試操作實踐,相信大家應(yīng)該對 HttpRunner v4.0 的性能測試使用方法有了一個整體的認(rèn)識。
歡迎大家多多實踐,如果在使用過程中遇到任何問題,歡迎通過各種渠道進(jìn)行反饋,我們將及時進(jìn)行跟進(jìn)和解答,并基于大家的反饋進(jìn)行迭代優(yōu)化。
希望本文對你有所幫助~~如果對軟件測試、接口測試、自動化測試、性能測試、面試經(jīng)驗交流感興趣可以私聊我或關(guān)注公眾號“特斯汀軟件測試”。免費領(lǐng)取最新軟件測試大廠面試資料和Python自動化、接口、框架搭建學(xué)習(xí)資料!技術(shù)大牛解惑答疑,同行一起交流。