mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 19:39:44 +08:00
Merge branch 'master' into ios-wda
This commit is contained in:
@@ -1,20 +1,19 @@
|
||||
# Release History
|
||||
|
||||
## v4.2.0 (2022-07-26)
|
||||
## v4.2.0 (2022-08-21)
|
||||
|
||||
**go version**
|
||||
|
||||
- feat: support distributed load testing on multi-machines
|
||||
- feat: support run/boom/convert curl command(s)
|
||||
- feat: support uploading file with indicated type and filename
|
||||
- feat: support to infer MIME type of the uploaded file automatically
|
||||
- feat: using `@FILEPATH` to indicate the path of the file
|
||||
- feat: add ping/dns/traceroute/curl sub commands
|
||||
- feat: improve builtin uploading feature, support `@` indicator and inferring MIME type
|
||||
- feat: hrp boom support setting duration of run time
|
||||
- change: support omitting websocket url if not necessary
|
||||
- change: support multiple websocket connections for each session
|
||||
- fix: optimize websocket step initialization
|
||||
- fix: reuse plugin instance if already initialized
|
||||
- fix: deep copy api step to avoid data racing
|
||||
- feat: support ping/dns/traceroute for dial test
|
||||
|
||||
## v4.1.6 (2022-07-04)
|
||||
|
||||
|
||||
@@ -32,9 +32,13 @@ Copyright 2017 debugtalk
|
||||
* [hrp boom](hrp_boom.md) - run load test with boomer
|
||||
* [hrp build](hrp_build.md) - build plugin for testing
|
||||
* [hrp convert](hrp_convert.md) - convert to JSON/YAML/gotest/pytest testcases
|
||||
* [hrp curl](hrp_curl.md) - run integrated curl command
|
||||
* [hrp dns](hrp_dns.md) - DNS resolution for different source and record types
|
||||
* [hrp ping](hrp_ping.md) - run integrated ping command
|
||||
* [hrp pytest](hrp_pytest.md) - run API test with pytest
|
||||
* [hrp run](hrp_run.md) - run API test with go engine
|
||||
* [hrp startproject](hrp_startproject.md) - create a scaffold project
|
||||
* [hrp traceroute](hrp_traceroute.md) - run integrated traceroute command
|
||||
* [hrp wiki](hrp_wiki.md) - visit https://httprunner.com
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -54,4 +54,4 @@ hrp boom [flags]
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
* [hrp boom curl](hrp_boom_curl.md) - run load test with curl command
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -16,4 +16,4 @@ hrp boom curl URLs [flags]
|
||||
|
||||
* [hrp boom](hrp_boom.md) - run load test with boomer
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -28,4 +28,4 @@ hrp build $path ... [flags]
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -23,4 +23,4 @@ hrp convert $path... [flags]
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
* [hrp convert curl](hrp_convert_curl.md) - convert curl command to httprunner testcase
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -16,4 +16,4 @@ hrp convert curl URLs [flags]
|
||||
|
||||
* [hrp convert](hrp_convert.md) - convert to JSON/YAML/gotest/pytest testcases
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
19
docs/cmd/hrp_curl.md
Normal file
19
docs/cmd/hrp_curl.md
Normal file
@@ -0,0 +1,19 @@
|
||||
## hrp curl
|
||||
|
||||
run integrated curl command
|
||||
|
||||
```
|
||||
hrp curl $url [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for curl
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
29
docs/cmd/hrp_dns.md
Normal file
29
docs/cmd/hrp_dns.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## hrp dns
|
||||
|
||||
DNS resolution for different source and record types
|
||||
|
||||
```
|
||||
hrp dns $url [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--dns-record int DNS record type
|
||||
1: A
|
||||
28: AAAA
|
||||
5: CNAME (default 1)
|
||||
--dns-server string DNS server, only available for local DNS source
|
||||
--dns-source int DNS source type
|
||||
0: local DNS
|
||||
1: http DNS
|
||||
2: google DNS
|
||||
-h, --help help for dns
|
||||
--save-tests Save DNS resolution result as json
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
23
docs/cmd/hrp_ping.md
Normal file
23
docs/cmd/hrp_ping.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## hrp ping
|
||||
|
||||
run integrated ping command
|
||||
|
||||
```
|
||||
hrp ping $url [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-c, --count int Stop after sending (and receiving) N packets (default 10)
|
||||
-h, --help help for ping
|
||||
-i, --interval duration Wait N seconds between sending each packet (default 1s)
|
||||
--save-tests Save ping result as json
|
||||
-t, --timeout duration Ping exits after N seconds (default 20s)
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
@@ -16,4 +16,4 @@ hrp pytest $path ... [flags]
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -36,4 +36,4 @@ hrp run $path... [flags]
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
* [hrp run curl](hrp_run_curl.md) - run API test with curl command
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -16,4 +16,4 @@ hrp run curl URLs [flags]
|
||||
|
||||
* [hrp run](hrp_run.md) - run API test with go engine
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -21,4 +21,4 @@ hrp startproject $project_name [flags]
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
22
docs/cmd/hrp_traceroute.md
Normal file
22
docs/cmd/hrp_traceroute.md
Normal file
@@ -0,0 +1,22 @@
|
||||
## hrp traceroute
|
||||
|
||||
run integrated traceroute command
|
||||
|
||||
```
|
||||
hrp traceroute $url [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for traceroute
|
||||
-m, --max-hops int Set the max number of hops (max TTL to be reached) (default 30)
|
||||
-q, --queries int Set the number of probes per each hop (default 1)
|
||||
--save-tests Save traceroute result as json
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
@@ -16,4 +16,4 @@ hrp wiki [flags]
|
||||
|
||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||
|
||||
###### Auto generated by spf13/cobra on 26-Jul-2022
|
||||
###### Auto generated by spf13/cobra on 21-Aug-2022
|
||||
|
||||
@@ -65,6 +65,7 @@ func (b *HRPBoomer) InitBoomer() {
|
||||
}
|
||||
b.SetSpawnCount(b.GetProfile().SpawnCount)
|
||||
b.SetSpawnRate(b.GetProfile().SpawnRate)
|
||||
b.SetRunTime(b.GetProfile().RunTime)
|
||||
if b.GetProfile().LoopCount > 0 {
|
||||
b.SetLoopCount(b.GetProfile().LoopCount)
|
||||
}
|
||||
@@ -251,6 +252,7 @@ func (b *HRPBoomer) rebalanceRunner(profile *boomer.Profile) {
|
||||
log.Info().Interface("profile", profile).Msg("rebalance tasks successfully")
|
||||
}
|
||||
|
||||
|
||||
func (b *HRPBoomer) PollTasks(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
|
||||
@@ -67,6 +67,7 @@ var boomCmd = &cobra.Command{
|
||||
hrpBoomer.SetExpectWorkers(boomArgs.expectWorkers, boomArgs.expectWorkersMaxWait)
|
||||
hrpBoomer.SetSpawnCount(boomArgs.SpawnCount)
|
||||
hrpBoomer.SetSpawnRate(boomArgs.SpawnRate)
|
||||
hrpBoomer.SetRunTime(boomArgs.RunTime)
|
||||
}
|
||||
if boomArgs.autoStart {
|
||||
hrpBoomer.InitBoomer()
|
||||
@@ -116,6 +117,7 @@ func init() {
|
||||
boomCmd.Flags().StringVar(&boomArgs.RequestIncreaseRate, "request-increase-rate", "-1", "Request increase rate, disabled by default.")
|
||||
boomCmd.Flags().Int64Var(&boomArgs.SpawnCount, "spawn-count", 1, "The number of users to spawn for load testing")
|
||||
boomCmd.Flags().Float64Var(&boomArgs.SpawnRate, "spawn-rate", 1, "The rate for spawning users")
|
||||
boomCmd.Flags().Int64Var(&boomArgs.RunTime, "run-time", 0, "Stop after the specified amount of time(s), Only used --autostart. Defaults to run forever.")
|
||||
boomCmd.Flags().Int64Var(&boomArgs.LoopCount, "loop-count", -1, "The specify running cycles for load testing")
|
||||
boomCmd.Flags().StringVar(&boomArgs.MemoryProfile, "mem-profile", "", "Enable memory profiling.")
|
||||
boomCmd.Flags().DurationVar(&boomArgs.MemoryProfileDuration, "mem-profile-duration", 30*time.Second, "Memory profile duration.")
|
||||
|
||||
@@ -50,6 +50,7 @@ type Boomer struct {
|
||||
type Profile struct {
|
||||
SpawnCount int64 `json:"spawn-count,omitempty" yaml:"spawn-count,omitempty" mapstructure:"spawn-count,omitempty"`
|
||||
SpawnRate float64 `json:"spawn-rate,omitempty" yaml:"spawn-rate,omitempty" mapstructure:"spawn-rate,omitempty"`
|
||||
RunTime int64 `json:"run-time,omitempty" yaml:"run-time,omitempty" mapstructure:"run-time,omitempty"`
|
||||
MaxRPS int64 `json:"max-rps,omitempty" yaml:"max-rps,omitempty" mapstructure:"max-rps,omitempty"`
|
||||
LoopCount int64 `json:"loop-count,omitempty" yaml:"loop-count,omitempty" mapstructure:"loop-count,omitempty"`
|
||||
RequestIncreaseRate string `json:"request-increase-rate,omitempty" yaml:"request-increase-rate,omitempty" mapstructure:"request-increase-rate,omitempty"`
|
||||
@@ -274,6 +275,18 @@ func (b *Boomer) SetSpawnRate(spawnRate float64) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetRunTime sets run time
|
||||
func (b *Boomer) SetRunTime(runTime int64) {
|
||||
switch b.mode {
|
||||
case DistributedMasterMode:
|
||||
b.masterRunner.setRunTime(runTime)
|
||||
case DistributedWorkerMode:
|
||||
b.workerRunner.setRunTime(runTime)
|
||||
default:
|
||||
b.localRunner.setRunTime(runTime)
|
||||
}
|
||||
}
|
||||
|
||||
// SetExpectWorkers sets expect workers while load testing
|
||||
func (b *Boomer) SetExpectWorkers(expectWorkers int, expectWorkersMaxWait int) {
|
||||
b.masterRunner.setExpectWorkers(expectWorkers, expectWorkersMaxWait)
|
||||
@@ -497,6 +510,7 @@ func (b *Boomer) Start(Args *Profile) error {
|
||||
}
|
||||
b.SetSpawnCount(Args.SpawnCount)
|
||||
b.SetSpawnRate(Args.SpawnRate)
|
||||
b.SetRunTime(Args.RunTime)
|
||||
b.SetProfile(Args)
|
||||
err := b.masterRunner.start()
|
||||
return err
|
||||
@@ -512,6 +526,7 @@ func (b *Boomer) ReBalance(Args *Profile) error {
|
||||
}
|
||||
b.SetSpawnCount(Args.SpawnCount)
|
||||
b.SetSpawnRate(Args.SpawnRate)
|
||||
b.SetRunTime(Args.RunTime)
|
||||
b.SetProfile(Args)
|
||||
err := b.masterRunner.rebalance()
|
||||
if err != nil {
|
||||
|
||||
@@ -203,6 +203,7 @@ type runner struct {
|
||||
|
||||
spawnCount int64 // target clients to spawn
|
||||
spawnRate float64
|
||||
runTime int64
|
||||
|
||||
controller *Controller
|
||||
loop *Loop // specify loop count for testcase, count = loopCount * spawnCount
|
||||
@@ -243,6 +244,14 @@ func (r *runner) getSpawnRate() float64 {
|
||||
return r.spawnRate
|
||||
}
|
||||
|
||||
func (r *runner) setRunTime(runTime int64) {
|
||||
atomic.StoreInt64(&r.runTime, time.Now().Unix()+runTime)
|
||||
}
|
||||
|
||||
func (r *runner) getRunTime() int64 {
|
||||
return atomic.LoadInt64(&r.runTime)
|
||||
}
|
||||
|
||||
func (r *runner) getSpawnCount() int64 {
|
||||
return atomic.LoadInt64(&r.spawnCount)
|
||||
}
|
||||
@@ -368,6 +377,26 @@ func (r *runner) reset() {
|
||||
r.reportedChan = make(chan bool)
|
||||
}
|
||||
|
||||
func (r *runner) runTimeCheck(runTime int64) {
|
||||
if runTime <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var ticker = time.NewTicker(time.Second * 3)
|
||||
for {
|
||||
select {
|
||||
case <-r.stopChan:
|
||||
return
|
||||
case <-ticker.C:
|
||||
nowTime := time.Now().Unix()
|
||||
if nowTime > runTime {
|
||||
r.stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *runner) spawnWorkers(spawnCount int64, spawnRate float64, quit chan bool, spawnCompleteFunc func()) {
|
||||
r.updateState(StateSpawning)
|
||||
log.Info().
|
||||
@@ -628,6 +657,8 @@ func (r *localRunner) start() {
|
||||
// output setup
|
||||
r.outputOnStart()
|
||||
|
||||
go r.runTimeCheck(r.getRunTime())
|
||||
|
||||
go r.spawnWorkers(r.getSpawnCount(), r.getSpawnRate(), r.stoppingChan, nil)
|
||||
|
||||
defer func() {
|
||||
@@ -923,6 +954,8 @@ func (r *workerRunner) start() {
|
||||
|
||||
r.outputOnStart()
|
||||
|
||||
go r.runTimeCheck(r.getRunTime())
|
||||
|
||||
go r.spawnWorkers(r.getSpawnCount(), r.getSpawnRate(), r.stoppingChan, r.spawnComplete)
|
||||
|
||||
defer func() {
|
||||
|
||||
Reference in New Issue
Block a user