-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
golang lib for benchmarking and load testing.
- Loading branch information
Showing
14 changed files
with
1,551 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
language: go | ||
|
||
go: | ||
- 1.11.x | ||
- 1.12.x | ||
- 1.13.x | ||
- 1.14.x |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,107 @@ | ||
# spidomtr | ||
# spidomtr | ||
[![Build Status](https://travis-ci.org/spider-pigs/spidomtr.svg?branch=master)](https://travis-ci.org/spider-pigs/spidomtr) [![Go Report Card](https://goreportcard.com/badge/github.com/spider-pigs/spidomtr)](https://goreportcard.com/report/github.com/spider-pigs/spidomtr) [![GoDoc](https://godoc.org/github.com/spider-pigs/spidomtr?status.svg)](https://godoc.org/github.com/spider-pigs/spidomtr) | ||
|
||
spidomtr is a golang lib for benchmarking and load testing. | ||
|
||
```console | ||
.__ .___ __ | ||
____________ |__| __| _/____ ______/ |________ | ||
/ ___/\____ \| |/ __ |/ _ \ / \ __\_ __ \ | ||
\___ \ | |_> > / /_/ ( <_> ) Y Y \ | | | \/ | ||
/____ >| __/|__\____ |\____/|__|_| /__| |__| | ||
\/ |__| \/ \/ | ||
|
||
[====================================================================] 100% 3s | ||
|
||
Summary: | ||
Count: 500 | ||
Total: 3.391898304s | ||
Slowest: 104 ms | ||
Fastest: 21 ms | ||
Average: 61 ms | ||
Req/sec: 147.41 | ||
|
||
Response time histogram: | ||
21 ms [1] | | ||
37 ms [94] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | ||
54 ms [120] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | ||
70 ms [95] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | ||
87 ms [104] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | ||
104 ms [86] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ | ||
|
||
Latency distribution: | ||
10% in 30 ms | ||
25% in 42 ms | ||
50% in 59 ms | ||
75% in 81 ms | ||
90% in 93 ms | ||
95% in 97 ms | ||
99% in 101 ms | ||
|
||
Responses: | ||
OK: 500 | ||
Errored: 0 | ||
Skipped: 0 | ||
|
||
Tests: | ||
√ awesome_test | ||
Count: 500 | ||
OK: 500 | ||
Errored: 0 | ||
Skipped: 0 | ||
Slowest: 104 ms | ||
Fastest: 21 ms | ||
Average: 61 ms | ||
90%: 93 ms | ||
95%: 97 ms | ||
99%: 101 ms | ||
Req/sec: 147.41 | ||
``` | ||
|
||
# Install | ||
```golang | ||
import "github.com/spider-pigs/spidomtr" | ||
``` | ||
|
||
# Usage | ||
```golang | ||
package main | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/spider-pigs/spidomtr" | ||
"github.com/spider-pigs/spidomtr/pkg/handlers" | ||
"github.com/spider-pigs/spidomtr/pkg/testunit" | ||
) | ||
|
||
func main() { | ||
// Create the test runner | ||
runner := spidomtr.NewRunner( | ||
spidomtr.ID("awesome tests"), | ||
spidomtr.Description("just running some awesome tests"), | ||
spidomtr.Handlers( | ||
handlers.ProgressBar(), // Displays progress bar during test run | ||
), | ||
spidomtr.Iterations(50), // Run the test 50 times | ||
spidomtr.Timeout(time.Second*20), // Set a test timeout | ||
spidomtr.Users(10), // Simulate 10 concurrent users | ||
) | ||
|
||
// Create a test | ||
test := testunit.New( | ||
testunit.Test(func(ctx context.Context, args []interface{}) ([]interface{}, error) { | ||
if err := doSomethingCool(ctx); err != nil { | ||
// Test failed | ||
return args, err | ||
} | ||
// Test passed | ||
return args, nil | ||
}), | ||
) | ||
|
||
// Run the test | ||
res := runner.Run(context.Background(), test) | ||
... | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module github.com/spider-pigs/spidomtr | ||
|
||
require ( | ||
github.com/cheggaaa/pb/v3 v3.0.4 | ||
github.com/google/uuid v1.1.1 | ||
github.com/stretchr/testify v1.5.1 | ||
github.com/thepatrik/strcolor v1.0.3 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= | ||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= | ||
github.com/cheggaaa/pb/v3 v3.0.4 h1:QZEPYOj2ix6d5oEg63fbHmpolrnNiwjUsk+h74Yt4bM= | ||
github.com/cheggaaa/pb/v3 v3.0.4/go.mod h1:7rgWxLrAUcFMkvJuv09+DYi7mMUYi8nO9iOWcvGJPfw= | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= | ||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= | ||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= | ||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= | ||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= | ||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= | ||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= | ||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= | ||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= | ||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | ||
github.com/thepatrik/strcolor v1.0.3 h1:lFuGZwKJn1CwbXYagm8jVKmLh9FPCrd3T7FGSm4jEjc= | ||
github.com/thepatrik/strcolor v1.0.3/go.mod h1:I519L4XnoZZmMJauibTGgy7XODjJ1st3IusYns7MOrg= | ||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU= | ||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | ||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package runner | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/spider-pigs/spidomtr/pkg/testunit" | ||
) | ||
|
||
// TestUnitDone type | ||
type TestUnitDone func(testunit.TestUnit, *Timer, error) | ||
|
||
// Runner type | ||
type Runner struct { | ||
Iterations int | ||
TestUnitDone TestUnitDone | ||
Timeout time.Duration | ||
} | ||
|
||
// New constructs a new | ||
func New(timeout time.Duration, iterations int) *Runner { | ||
return &Runner{ | ||
Iterations: iterations, | ||
Timeout: timeout, | ||
} | ||
} | ||
|
||
// Run runs test units. | ||
func (runner Runner) Run(ctx context.Context, tests ...testunit.TestUnit) *Timer { | ||
totalTimer := NewTimer() | ||
totalTimer.Begin() | ||
|
||
for i := 0; i < runner.Iterations; i++ { | ||
for _, t := range tests { | ||
var err error | ||
timer := NewTimer() | ||
|
||
enabled, _ := t.Enabled() | ||
if enabled { | ||
timer, err = runTestUnit(ctx, t, runner.Timeout) | ||
} | ||
if runner.TestUnitDone != nil { | ||
runner.TestUnitDone(t, timer, err) | ||
} | ||
} | ||
} | ||
|
||
totalTimer.Finish() | ||
return totalTimer | ||
} | ||
|
||
func runTestUnit(ctx context.Context, t testunit.TestUnit, timeout time.Duration) (*Timer, error) { | ||
timer := NewTimer() | ||
var err error | ||
var wg sync.WaitGroup | ||
wg.Add(1) | ||
|
||
go func() { | ||
defer wg.Done() | ||
defer func() { | ||
if r := recover(); r != nil { | ||
panicstr := fmt.Sprintf("%s", r) | ||
err = errors.New("func panic: " + panicstr) | ||
} | ||
}() | ||
ctx, cancel := context.WithTimeout(ctx, timeout) | ||
defer cancel() | ||
|
||
// Run prepare func | ||
var args []interface{} | ||
args, err = t.Prepare(ctx) | ||
if err != nil { | ||
return | ||
} | ||
|
||
// Run main func | ||
timer.Begin() | ||
args, err = t.Test(ctx, args) | ||
timer.Finish() | ||
|
||
if err != nil { | ||
return | ||
} | ||
|
||
// Run cleanup func | ||
err = t.Cleanup(ctx, args) | ||
}() | ||
wg.Wait() | ||
if err != nil { | ||
return NewTimer(), err | ||
} | ||
|
||
return timer, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package runner | ||
|
||
import "time" | ||
|
||
// Timer type | ||
type Timer struct { | ||
Start time.Time | ||
End time.Time | ||
Duration time.Duration | ||
} | ||
|
||
// NewTimer creates timer | ||
func NewTimer() *Timer { | ||
return &Timer{} | ||
} | ||
|
||
// Begin starts timer | ||
func (timer *Timer) Begin() { | ||
timer.Start = time.Now() | ||
} | ||
|
||
// Finish stops timer | ||
func (timer *Timer) Finish() { | ||
timer.End = time.Now() | ||
timer.Duration = timer.End.Sub(timer.Start) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package handlers | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"os" | ||
"strings" | ||
"unicode/utf8" | ||
|
||
"github.com/spider-pigs/spidomtr" | ||
"github.com/spider-pigs/spidomtr/pkg/testunit" | ||
"github.com/thepatrik/strcolor" | ||
) | ||
|
||
const ( | ||
checkMark = "√" | ||
crossMark = "☓" | ||
skipMark = "-" | ||
) | ||
|
||
// TestLogger type | ||
type TestLogger struct { | ||
Log *log.Logger | ||
Buffer *bytes.Buffer | ||
} | ||
|
||
// Logger logs tests during the test run | ||
func Logger() spidomtr.RunnerHandler { | ||
return &TestLogger{} | ||
} | ||
|
||
// RunnerStarted is called when runner is started (prior to any tests | ||
// have been run). | ||
func (logger *TestLogger) RunnerStarted(id, description string, count int) { | ||
logger.Log = log.New(os.Stdout, "", 0) | ||
logger.Buffer = &bytes.Buffer{} | ||
|
||
fmt.Fprintf(logger.Buffer, "Running %s: %s...\n", id, description) | ||
logger.Log.Printf("Running %s: %s\n", id, description) | ||
} | ||
|
||
// TestDone is called when a test has been completed. | ||
func (logger *TestLogger) TestDone(res spidomtr.TestResult) { | ||
switch res.Outcome { | ||
case testunit.Skip: | ||
fmt.Fprintf(logger.Buffer, "%s %s: %s\n", skipMark, res.ID, res.Comment) | ||
logger.Log.Printf("%s %s: %s\n", strcolor.Yellow(skipMark), res.ID, res.Comment) | ||
case testunit.Fail: | ||
fmt.Fprintf(logger.Buffer, "%s %s: %s\n", crossMark, res.ID, res.Error) | ||
logger.Log.Printf("%s %s: %s\n", strcolor.Red(crossMark), res.ID, res.Error) | ||
case testunit.Pass: | ||
fmt.Fprintf(logger.Buffer, "%s %s: %s\n", checkMark, res.ID, res.Duration) | ||
logger.Log.Printf("%s %s: %s\n", strcolor.Green(checkMark), res.ID, res.Duration) | ||
} | ||
} | ||
|
||
// RunnerDone is called when the runner has run all tests. | ||
func (logger *TestLogger) RunnerDone(res spidomtr.Result) { | ||
mark := func() strcolor.StrColor { | ||
switch { | ||
case res.Stats.Errors > 0: | ||
return strcolor.Red(crossMark) | ||
case res.Stats.Skips > 0: | ||
return strcolor.Yellow(skipMark) | ||
} | ||
return strcolor.Green(checkMark) | ||
}() | ||
|
||
str := fmt.Sprintf("%d/%d passed, %d failed, %d skipped, took %s, avg %s/test", res.Stats.Passed, res.Stats.Count, res.Stats.Errors, res.Stats.Skips, res.Stats.Duration, res.Stats.Average) | ||
divider := strings.Repeat("-", utf8.RuneCountInString(str)+2) | ||
|
||
fmt.Fprintf(logger.Buffer, "%s\n%s %s\n%s\n", divider, mark.Val, str, divider) | ||
logger.Log.Printf("%s\n%s %s\n%s\n", divider, mark, str, divider) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package handlers | ||
|
||
import ( | ||
"github.com/cheggaaa/pb/v3" | ||
"github.com/spider-pigs/spidomtr" | ||
) | ||
|
||
type progressBar struct { | ||
bar *pb.ProgressBar | ||
} | ||
|
||
// ProgressBar is a runner handler that displays a running progress | ||
// bar. | ||
func ProgressBar() spidomtr.RunnerHandler { | ||
return &progressBar{} | ||
} | ||
|
||
// RunnerStarted is called when runner is started (prior to any tests | ||
// have been run). | ||
func (b *progressBar) RunnerStarted(id, description string, count int) { | ||
b.bar = pb.StartNew(count) | ||
} | ||
|
||
// TestDone is called when a test has been completed. | ||
func (b *progressBar) TestDone(spidomtr.TestResult) { | ||
b.bar.Increment() | ||
} | ||
|
||
// RunnerDone is called when the runner has run all tests. | ||
func (b *progressBar) RunnerDone(spidomtr.Result) { | ||
b.bar.Finish() | ||
} |
Oops, something went wrong.