mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-09 06:23:52 +08:00
Merge pull request #138 from xucong053/support-test-result-for-load-testing
feat: print statistics summary after load testing finished
This commit is contained in:
@@ -43,6 +43,7 @@ var boomCmd = &cobra.Command{
|
|||||||
hrpBoomer.SetDisableCompression(disableCompression)
|
hrpBoomer.SetDisableCompression(disableCompression)
|
||||||
hrpBoomer.EnableCPUProfile(cpuProfile, cpuProfileDuration)
|
hrpBoomer.EnableCPUProfile(cpuProfile, cpuProfileDuration)
|
||||||
hrpBoomer.EnableMemoryProfile(memoryProfile, memoryProfileDuration)
|
hrpBoomer.EnableMemoryProfile(memoryProfile, memoryProfileDuration)
|
||||||
|
hrpBoomer.EnableGracefulQuit()
|
||||||
hrpBoomer.Run(paths...)
|
hrpBoomer.Run(paths...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package boomer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@@ -95,6 +98,16 @@ func (b *Boomer) EnableMemoryProfile(memoryProfile string, duration time.Duratio
|
|||||||
b.memoryProfileDuration = duration
|
b.memoryProfileDuration = duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnableGracefulQuit catch SIGINT and SIGTERM signals to quit gracefully
|
||||||
|
func (b *Boomer) EnableGracefulQuit() {
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
|
||||||
|
go func() {
|
||||||
|
<-c
|
||||||
|
b.Quit()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
// Run accepts a slice of Task and connects to the locust master.
|
// Run accepts a slice of Task and connects to the locust master.
|
||||||
func (b *Boomer) Run(tasks ...*Task) {
|
func (b *Boomer) Run(tasks ...*Task) {
|
||||||
if b.cpuProfile != "" {
|
if b.cpuProfile != "" {
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/olekukonko/tablewriter"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -144,6 +147,36 @@ func (r *runner) reportStats() {
|
|||||||
r.outputOnEvent(data)
|
r.outputOnEvent(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *runner) reportTestResult() {
|
||||||
|
// convert stats in total
|
||||||
|
var statsTotal interface{} = r.stats.total.serialize()
|
||||||
|
entryTotalOutput, err := deserializeStatsEntry(statsTotal)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
duration := time.Duration(entryTotalOutput.LastRequestTimestamp-entryTotalOutput.StartTime) * time.Second
|
||||||
|
currentTime := time.Now()
|
||||||
|
println(fmt.Sprint("=========================================== Statistics Summary =========================================="))
|
||||||
|
println(fmt.Sprintf("Current time: %s, Users: %v, Duration: %v, Accumulated Transactions: %d Passed, %d Failed",
|
||||||
|
currentTime.Format("2006/01/02 15:04:05"), atomic.LoadInt32(&r.currentClientsNum), duration, r.stats.transactionPassed, r.stats.transactionFailed))
|
||||||
|
table := tablewriter.NewWriter(os.Stdout)
|
||||||
|
table.SetHeader([]string{"Name", "# requests", "# fails", "Median", "Average", "Min", "Max", "Content Size", "# reqs/sec", "# fails/sec"})
|
||||||
|
row := make([]string, 10)
|
||||||
|
row[0] = entryTotalOutput.Name
|
||||||
|
row[1] = strconv.FormatInt(entryTotalOutput.NumRequests, 10)
|
||||||
|
row[2] = strconv.FormatInt(entryTotalOutput.NumFailures, 10)
|
||||||
|
row[3] = strconv.FormatInt(entryTotalOutput.medianResponseTime, 10)
|
||||||
|
row[4] = strconv.FormatFloat(entryTotalOutput.avgResponseTime, 'f', 2, 64)
|
||||||
|
row[5] = strconv.FormatInt(entryTotalOutput.MinResponseTime, 10)
|
||||||
|
row[6] = strconv.FormatInt(entryTotalOutput.MaxResponseTime, 10)
|
||||||
|
row[7] = strconv.FormatInt(entryTotalOutput.avgContentLength, 10)
|
||||||
|
row[8] = strconv.FormatFloat(entryTotalOutput.currentRps, 'f', 2, 64)
|
||||||
|
row[9] = strconv.FormatFloat(entryTotalOutput.currentFailPerSec, 'f', 2, 64)
|
||||||
|
table.Append(row)
|
||||||
|
table.Render()
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *localRunner) spawnWorkers(spawnCount int, spawnRate float64, quit chan bool, spawnCompleteFunc func()) {
|
func (r *localRunner) spawnWorkers(spawnCount int, spawnRate float64, quit chan bool, spawnCompleteFunc func()) {
|
||||||
log.Info().
|
log.Info().
|
||||||
Int("spawnCount", spawnCount).
|
Int("spawnCount", spawnCount).
|
||||||
@@ -324,6 +357,9 @@ func (r *localRunner) start() {
|
|||||||
r.rateLimiter.Stop()
|
r.rateLimiter.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// report test result
|
||||||
|
r.reportTestResult()
|
||||||
|
|
||||||
// output teardown
|
// output teardown
|
||||||
r.outputOnStop()
|
r.outputOnStop()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user