Add e2e tests

This commit is contained in:
2026-02-18 00:03:59 +04:00
parent d197e90103
commit 4b3230bb27
26 changed files with 4490 additions and 3 deletions

220
e2e/basic_test.go Normal file
View File

@@ -0,0 +1,220 @@
package e2e
import (
"strconv"
"testing"
)
func TestNoArgs(t *testing.T) {
t.Parallel()
res := run()
assertExitCode(t, res, 1)
// With no args and no env vars, validation should fail on required fields
assertContains(t, res.Stderr, "VALIDATION")
}
func TestHelp(t *testing.T) {
t.Parallel()
for _, flag := range []string{"-h", "-help"} {
t.Run(flag, func(t *testing.T) {
t.Parallel()
res := run(flag)
assertContains(t, res.Stdout, "Usage:")
assertContains(t, res.Stdout, "-url")
})
}
}
func TestVersion(t *testing.T) {
t.Parallel()
for _, flag := range []string{"-v", "-version"} {
t.Run(flag, func(t *testing.T) {
t.Parallel()
res := run(flag)
assertExitCode(t, res, 0)
assertContains(t, res.Stdout, "Version:")
assertContains(t, res.Stdout, "Git Commit:")
})
}
}
func TestUnexpectedArgs(t *testing.T) {
t.Parallel()
res := run("-U", "http://example.com", "unexpected")
assertExitCode(t, res, 1)
assertContains(t, res.Stderr, "Unexpected CLI arguments")
}
func TestSimpleRequest(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-r", "3", "-q", "-o", "json")
assertExitCode(t, res, 0)
out := res.jsonOutput(t)
assertHasResponseKey(t, out, "200")
assertResponseCount(t, out, 3)
}
func TestDryRun(t *testing.T) {
t.Parallel()
res := run("-U", "http://example.com", "-r", "5", "-q", "-o", "json", "-z")
assertExitCode(t, res, 0)
out := res.jsonOutput(t)
assertHasResponseKey(t, out, "dry-run")
assertResponseCount(t, out, 5)
}
func TestDryRunDoesNotSendRequests(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "5", "-q", "-o", "json", "-z")
assertExitCode(t, res, 0)
if cs.requestCount() != 0 {
t.Errorf("dry-run should not send any requests, but server received %d", cs.requestCount())
}
}
func TestQuietMode(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-r", "1", "-q", "-o", "json")
assertExitCode(t, res, 0)
if res.Stderr != "" {
t.Errorf("expected empty stderr in quiet mode, got: %s", res.Stderr)
}
}
func TestOutputNone(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-r", "1", "-q", "-o", "none")
assertExitCode(t, res, 0)
if res.Stdout != "" {
t.Errorf("expected empty stdout with -o none, got: %s", res.Stdout)
}
}
func TestOutputJSON(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-r", "1", "-q", "-o", "json")
assertExitCode(t, res, 0)
out := res.jsonOutput(t)
if out.Responses == nil {
t.Fatal("responses field is nil")
}
if out.Total.Min == "" || out.Total.Max == "" || out.Total.Average == "" {
t.Errorf("total stats are incomplete: %+v", out.Total)
}
if out.Total.P90 == "" || out.Total.P95 == "" || out.Total.P99 == "" {
t.Errorf("total percentiles are incomplete: %+v", out.Total)
}
}
func TestOutputYAML(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-r", "1", "-q", "-o", "yaml")
assertExitCode(t, res, 0)
assertContains(t, res.Stdout, "responses:")
assertContains(t, res.Stdout, "total:")
assertContains(t, res.Stdout, "count:")
}
func TestOutputTable(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-r", "1", "-q", "-o", "table")
assertExitCode(t, res, 0)
assertContains(t, res.Stdout, "Response")
assertContains(t, res.Stdout, "Count")
assertContains(t, res.Stdout, "Min")
assertContains(t, res.Stdout, "P99")
}
func TestInvalidOutputFormat(t *testing.T) {
t.Parallel()
res := run("-U", "http://example.com", "-r", "1", "-o", "invalid")
assertExitCode(t, res, 1)
assertContains(t, res.Stderr, "Output")
}
func TestStatusCodes(t *testing.T) {
t.Parallel()
codes := []int{200, 201, 204, 301, 400, 404, 500, 502}
for _, code := range codes {
t.Run(strconv.Itoa(code), func(t *testing.T) {
t.Parallel()
srv := statusServer(code)
defer srv.Close()
res := run("-U", srv.URL, "-r", "1", "-q", "-o", "json")
assertExitCode(t, res, 0)
out := res.jsonOutput(t)
assertHasResponseKey(t, out, strconv.Itoa(code))
})
}
}
func TestConcurrency(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-r", "10", "-c", "5", "-q", "-o", "json")
assertExitCode(t, res, 0)
out := res.jsonOutput(t)
assertResponseCount(t, out, 10)
}
func TestDuration(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
res := run("-U", srv.URL, "-d", "1s", "-q", "-o", "json")
assertExitCode(t, res, 0)
out := res.jsonOutput(t)
count, _ := out.Total.Count.Int64()
if count < 1 {
t.Errorf("expected at least 1 request during 1s duration, got %d", count)
}
}
func TestRequestsAndDuration(t *testing.T) {
t.Parallel()
srv := echoServer()
defer srv.Close()
// Both -r and -d set: should stop at whichever comes first
res := run("-U", srv.URL, "-r", "3", "-d", "10s", "-q", "-o", "json")
assertExitCode(t, res, 0)
out := res.jsonOutput(t)
assertResponseCount(t, out, 3)
}