Documentation
¶
Overview ¶
Package testkit provides deterministic, fluent test harnesses for both nexssp actions and standard Go http.Handler implementations.
Index ¶
- Constants
- func AssertContracts(t *testing.T, actions []action.AnyAction)
- func BenchAction[Req, Res any](b *testing.B, act *action.BuiltAction[Req, Res], req Req)
- func BenchHTTP(b *testing.B, s *Suite, method, path string, payload any)
- func Eventually(t testing.TB, timeout, interval time.Duration, condition func() bool)
- func MustError[Req, Res any](t testing.TB, fn action.Fn[Req, Res], req Req, want error)
- func MustExecute[Req, Res any](t testing.TB, fn action.Fn[Req, Res], req Req) Res
- func RunSmokeTests(t *testing.T, actions []action.AnyAction)
- func Script[Req, Res any](results ...Result[Res]) action.Fn[Req, Res]
- func Simulate[Req, Res any](t testing.TB, act *action.BuiltAction[Req, Res], req Req, concurrency int, ...)
- func WaitForJSON[T any](t testing.TB, timeout, interval time.Duration, ...) T
- func WithChaos(actions []action.AnyAction, cfg chaos.Config) []action.AnyAction
- type LoadConfig
- type LoadResult
- type Recorder
- func (r *Recorder[Req, Res]) OnCacheHit(context.Context, Req, Res)
- func (r *Recorder[Req, Res]) OnCacheMiss(context.Context, Req)
- func (r *Recorder[Req, Res]) OnCoalesced(context.Context, Req)
- func (r *Recorder[Req, Res]) OnDeduplicated(context.Context, Req)
- func (r *Recorder[Req, Res]) OnRetry(_ context.Context, req Req, attempt int, err error)
- type Request
- func (r *Request) Do() *Response
- func (r *Request) DoContext(ctx context.Context) (*Response, error)
- func (r *Request) DoE() (*Response, error)
- func (r *Request) WithBearerToken(token string) *Request
- func (r *Request) WithContext(ctx context.Context) *Request
- func (r *Request) WithCookie(name, value string) *Request
- func (r *Request) WithForm(data map[string]string) *Request
- func (r *Request) WithHeader(k, v string) *Request
- func (r *Request) WithJSON(v any) *Request
- func (r *Request) WithMultipartFile(fieldName, filename string, content []byte) *Request
- func (r *Request) WithQueries(params map[string]string) *Request
- func (r *Request) WithQuery(key, value string) *Request
- func (r *Request) WithTenant(tenantID string) *Request
- type Response
- func (c *Response) Body() []byte
- func (c *Response) BodyString() string
- func (c *Response) ContainsString(substr string) *Response
- func (c *Response) ExpectArrayLen(path string, n int) *Response
- func (c *Response) ExpectBadRequest() *Response
- func (c *Response) ExpectCreated() *Response
- func (c *Response) ExpectErrorKind(kind xerr.Kind, message string) *Response
- func (c *Response) ExpectForbidden() *Response
- func (c *Response) ExpectHeader(key, value string) *Response
- func (c *Response) ExpectNotFound() *Response
- func (c *Response) ExpectOK() *Response
- func (c *Response) ExpectStatus(code int) *Response
- func (c *Response) ExpectSuccess() *Response
- func (c *Response) ExpectUnauthorized() *Response
- func (c *Response) HasField(path string, expected any) *Response
- func (c *Response) Header(k string) string
- func (c *Response) Into(v any) *Response
- func (c *Response) Status() int
- type Result
- type RetryEvent
- type SSEEvent
- type StreamCapture
- func (sc *StreamCapture) Close()
- func (sc *StreamCapture) Endpoint(t testing.TB, timeout time.Duration) string
- func (sc *StreamCapture) WaitFor(t testing.TB, eventName string, timeout time.Duration) SSEEvent
- func (sc *StreamCapture) WaitForData(t testing.TB, substr string, timeout time.Duration) SSEEvent
- func (sc *StreamCapture) WaitForSSE(t testing.TB, timeout time.Duration, match func(SSEEvent) bool) SSEEvent
- func (sc *StreamCapture) WaitForSSEData(t testing.TB, substr string, timeout time.Duration) SSEEvent
- type Suite
- func (s *Suite) DELETE(path string, body ...any) *Request
- func (s *Suite) GET(path string, body ...any) *Request
- func (s *Suite) ListenSSE(path string) *StreamCapture
- func (s *Suite) ListenSSEWithRequest(t testing.TB, req *http.Request) *StreamCapture
- func (s *Suite) LoadTest(t *testing.T, cfg LoadConfig) LoadResult
- func (s *Suite) PATCH(path string, body ...any) *Request
- func (s *Suite) POST(path string, body ...any) *Request
- func (s *Suite) PUT(path string, body ...any) *Request
- func (s *Suite) Request(method, path string) *Request
- func (s *Suite) ResetHeaders() *Suite
- func (s *Suite) StartBackgroundLoad(cfg LoadConfig) func()
- func (s *Suite) WithCookie(name, value string) *Suite
- func (s *Suite) WithGlobalBearerToken(token string) *Suite
- func (s *Suite) WithGlobalHeader(key, value string) *Suite
Constants ¶
const (
HeaderTenantID = "X-Tenant-ID"
)
Variables ¶
This section is empty.
Functions ¶
func AssertContracts ¶
AssertContracts verifies architectural invariants across all registered actions. Catches duplicate action names, orphaned actions without routes/hooks, and malformed DTOs.
func BenchAction ¶
func BenchAction[Req, Res any](b *testing.B, act *action.BuiltAction[Req, Res], req Req)
BenchAction benchmarks a built action's pure execution speed without transport overhead.
func Eventually ¶ added in v0.3.0
Eventually repeatedly evaluates condition until it returns true or timeout expires. The condition is evaluated immediately before waiting for the first interval. It runs synchronously on the caller's goroutine and Eventually starts no goroutines.
func MustExecute ¶
func Simulate ¶
func Simulate[Req, Res any]( t testing.TB, act *action.BuiltAction[Req, Res], req Req, concurrency int, assertFn func(t testing.TB, res Res, err error), )
Simulate executes an action concurrently across N workers using a synchronized barrier to verify thread-safety, race conditions, and singleflight deduplication.
func WaitForJSON ¶ added in v0.3.0
func WaitForJSON[T any]( t testing.TB, timeout, interval time.Duration, request func() (*Response, error), ready func(T) bool, ) T
WaitForJSON repeats request until it returns a decodable JSON value accepted by ready, or timeout expires. request must build a fresh request on every call. Transient request and JSON-decoding errors are retried; the last error is included in the timeout failure when one is available.
This is intended for eventually consistent HTTP APIs. For ordinary one-shot assertions, use suite.GET(...).Do().Into(...) instead.
Types ¶
type LoadConfig ¶
type LoadResult ¶
type Recorder ¶
type Recorder[Req, Res any] struct { Retries []RetryEvent[Req] CacheHits int CacheMisses int Coalesced int Deduplicated int // contains filtered or unexported fields }
Recorder implements action.HookDispatcher with full goroutine concurrency safety.
func (*Recorder[Req, Res]) OnCacheHit ¶
func (*Recorder[Req, Res]) OnCacheMiss ¶
func (*Recorder[Req, Res]) OnCoalesced ¶
func (*Recorder[Req, Res]) OnDeduplicated ¶
type Request ¶
type Request struct {
// contains filtered or unexported fields
}
func (*Request) DoContext ¶
DoContext executes the HTTP request with the provided context and returns an error without calling t.Fatalf (goroutine safe).
func (*Request) WithBearerToken ¶
func (*Request) WithCookie ¶
func (*Request) WithHeader ¶
func (*Request) WithMultipartFile ¶
func (*Request) WithTenant ¶
type Response ¶
type Response struct {
// contains filtered or unexported fields
}
func (*Response) BodyString ¶
func (*Response) ContainsString ¶
func (*Response) ExpectBadRequest ¶
func (*Response) ExpectCreated ¶
func (*Response) ExpectErrorKind ¶
func (*Response) ExpectForbidden ¶
func (*Response) ExpectHeader ¶
func (*Response) ExpectNotFound ¶
func (*Response) ExpectStatus ¶
func (*Response) ExpectSuccess ¶
func (*Response) ExpectUnauthorized ¶
type RetryEvent ¶
type StreamCapture ¶
type StreamCapture struct {
// contains filtered or unexported fields
}
func (*StreamCapture) Close ¶
func (sc *StreamCapture) Close()
func (*StreamCapture) Endpoint ¶ added in v0.2.0
Endpoint conveniently extracts an MCP SSE endpoint event.
func (*StreamCapture) WaitForData ¶ added in v0.2.0
func (*StreamCapture) WaitForSSE ¶ added in v0.3.0
func (sc *StreamCapture) WaitForSSE(t testing.TB, timeout time.Duration, match func(SSEEvent) bool) SSEEvent
WaitForSSE waits for the first buffered SSE event accepted by match. Events that do not match are discarded, just like StreamCapture.WaitFor and WaitForData. A nil match predicate is rejected to avoid an accidental match-all wait; use WaitFor with an empty event name when matching any event.
func (*StreamCapture) WaitForSSEData ¶ added in v0.3.0
func (sc *StreamCapture) WaitForSSEData(t testing.TB, substr string, timeout time.Duration) SSEEvent
WaitForSSEData waits for an SSE event whose data contains substr. It is the predicate equivalent of StreamCapture.WaitForData and is useful when a test needs the event name as well as a data substring.
type Suite ¶
type Suite struct {
T testing.TB
Server *httptest.Server
// contains filtered or unexported fields
}
Suite wraps an in-memory or live HTTP server with fluent test assertions.
func NewWithHandler ¶
NewWithHandler initializes a test suite against ANY standard Go http.Handler.
func (*Suite) ListenSSE ¶
func (s *Suite) ListenSSE(path string) *StreamCapture
ListenSSE connects to an SSE endpoint using GET.
func (*Suite) ListenSSEWithRequest ¶ added in v0.2.0
ListenSSEWithRequest connects to an SSE endpoint using a custom HTTP request. This supports POST + SSE patterns such as MCP Streamable HTTP and A2A.
func (*Suite) LoadTest ¶
func (s *Suite) LoadTest(t *testing.T, cfg LoadConfig) LoadResult
LoadTest executes in-process stress tests, properly propagating cancellation to in-flight requests.
func (*Suite) ResetHeaders ¶
func (*Suite) StartBackgroundLoad ¶
func (s *Suite) StartBackgroundLoad(cfg LoadConfig) func()
StartBackgroundLoad generates background load, correctly checking for URL/request errors.