CLI tool for testing streaming endpoints -- SSE, WebSocket, and gRPC streaming.
Define tests in YAML, verify event ordering, measure latency, test reconnection, and validate backpressure handling. Built for CI pipelines.
Testing streaming endpoints is painful. You can curl a REST API, but how do you verify that:
- Your SSE endpoint sends events in the right order?
- WebSocket reconnection actually works with the correct Last-Event-ID?
- gRPC server streaming maintains sub-100ms p99 latency under load?
- Your streaming endpoint handles slow consumers without crashing?
Most teams write bespoke test scripts for each protocol. strmtest provides a single declarative format for all three streaming protocols, with built-in latency measurement, reconnection testing, and CI-friendly output.
go install github.com/JSLEEKR/strmtest/cmd/strmtest@latest# tests.yaml
version: "1"
tests:
- name: "SSE event ordering"
protocol: sse
endpoint: "http://localhost:8080/events"
timeout: 30s
expect:
events:
- type: "init"
data_contains: "connected"
- type: "update"
count: 5
ordering: sequential
latency:
p99: 100ms
max: 500ms
min_events: 6# Pretty output (default)
strmtest tests.yaml
# JSON output for CI
strmtest tests.yaml -f json
# TAP output
strmtest tests.yaml -f tap
# Verbose with latency stats
strmtest tests.yaml -v
# Validate spec without running
strmtest validate tests.yaml PASS [sse] SSE event ordering (150ms)
FAIL [ws] WebSocket echo (200ms)
- expected at least 5 events, got 2
ERR [sse] Connection test (2.0s)
Error: connection refused
FAIL 1/3 tests passed, 1 failed, 1 errors (2.4s)
| Protocol | Connect | Send | Receive | Reconnect | Latency | Backpressure |
|---|---|---|---|---|---|---|
| SSE | Y | -- | Y | Y | Y | Y |
| WebSocket | Y | Y | Y | Y | Y | Y |
| gRPC | Y | Y | Y | Y | Y | Y |
- Event type and data matching (contains, equals, regex)
- Event ID tracking and Last-Event-ID reconnection
- Retry field validation
- Multi-line data events
- Comment handling per SSE spec
- Text and binary frame support
- Send messages with configurable delays
- Ping/pong handler tracking
- Subprotocol negotiation
- Base64 encoding for binary data
- Server reflection for dynamic method discovery
- Server/client/bidirectional streaming
- Dynamic protobuf message construction from JSON
- TLS and metadata (headers) support
expect:
events:
- type: "update" # Match event type
data_contains: "hello" # Substring match
data_equals: "exact" # Exact match
data_regex: "^\\d+$" # Regex match
id_prefix: "evt-" # ID prefix match
count: 5 # Expected count
ordering: sequential # or "any"
min_events: 10
max_events: 100expect:
latency:
p50: 10ms
p95: 50ms
p99: 100ms
max: 500ms
avg: 30msreconnect:
enabled: true
max_retries: 3
delay: 2sbackpressure:
enabled: true
slow_consumer: 500ms # Simulate slow consumer
max_buffer_size: 100 # Buffer limit before dropping| Format | Use Case | Flag |
|---|---|---|
| pretty | Human-readable terminal output | -f pretty (default) |
| json | CI/CD integration, machine parsing | -f json |
| tap | TAP consumers (prove, tap-mocha-reporter) | -f tap |
| Code | Meaning |
|---|---|
| 0 | All tests passed |
| 1 | One or more tests failed |
| 2 | Configuration error |
| 3 | Connection error |
version: "1"
tests:
- name: "Test name" # Required
protocol: sse|ws|grpc # Required
endpoint: "url" # Required
headers: # Optional
Authorization: "Bearer token"
timeout: 30s # Optional (default: 30s)
# SSE-specific
last_event_id: "42" # Resume from event ID
# WebSocket-specific
subprotocol: "graphql-ws" # Subprotocol negotiation
send: # Messages to send
- type: text|binary
data: "raw string"
data_base64: "AQID" # Base64 for binary
delay: 100ms # Delay before sending
# gRPC-specific
service: "package.ServiceName" # gRPC service
method: "MethodName" # gRPC method
request: # JSON request body
field: "value"
tls: # TLS config
insecure: false
cert_file: "./cert.pem"
key_file: "./key.pem"
ca_file: "./ca.pem"
# Reconnection
reconnect:
enabled: true
max_retries: 3
delay: 1s
# Backpressure
backpressure:
enabled: true
slow_consumer: 500ms
max_buffer_size: 100
# Expectations
expect:
events: # SSE event matchers
- type: "event-type"
data_contains: "substring"
data_equals: "exact match"
data_regex: "pattern"
id_prefix: "prefix"
count: 5
messages: # WebSocket message matchers
- type: text|binary
data_contains: "substring"
ordering: sequential|any # Event ordering
min_events: 5 # Minimum event count
max_events: 100 # Maximum event count
latency:
p50: 10ms
p95: 50ms
p99: 100ms
max: 500ms
avg: 30ms
duration:
min: 1s
max: 10sSee the examples/ directory for complete test specs:
sse-basic.yaml-- SSE event ordering and reconnectionws-echo.yaml-- WebSocket echo, binary frames, authgrpc-stream.yaml-- gRPC server streaming with TLS
cmd/strmtest/ CLI entry point
internal/
config/ YAML spec parsing and validation
stream/ Common event types across protocols
sse/ SSE client implementation
ws/ WebSocket client (gorilla/websocket)
grpcstream/ gRPC streaming client (reflection-based)
matcher/ Event matching and validation
backpressure/ Backpressure detection and testing
runner/ Test execution orchestration
report/ Output formatting (pretty, JSON, TAP)
| Feature | strmtest | curl | wscat | grpcurl |
|---|---|---|---|---|
| SSE testing | Y | Partial | -- | -- |
| WebSocket testing | Y | -- | Partial | -- |
| gRPC streaming | Y | -- | -- | Y |
| Declarative YAML | Y | -- | -- | -- |
| Event ordering | Y | -- | -- | -- |
| Latency percentiles | Y | -- | -- | -- |
| Reconnect testing | Y | -- | -- | -- |
| Backpressure testing | Y | -- | -- | -- |
| CI-friendly output | Y | -- | -- | Partial |
| Single binary | Y | Y | -- | Y |
MIT