pwtest

package
v0.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package pwtest is the backend-neutral vocabulary a test uses to describe one request and inspect one response.

It exists because of a counting exercise. This repository drives handlers through httptest in 86 test files, 66 of them by building a request, calling a handler, and reading a recorder. Every one of those is written against net/http's request and response types, so porting the framework to a second transport without a seam means writing all 66 again — and a test written twice is two tests that can disagree about what the framework does, which is the opposite of what a test is for.

So the request and the response are described here, in types that name no transport, and each transport supplies one Exchange that runs the description through a real server of its own kind. A test written against this pair says the same thing on both, and the only line that differs is the import.

Why a real server rather than a recorder

A recorder is cheaper and answers a different question. Half of what a framework entry does is decided by the transport — whether the response commits, whether a header survives serialization, what a pooled request value carries — and a hand-built request value tests the entry against the test's idea of the transport rather than against the transport. Both Exchange implementations run a real server over an in-memory pipe, which costs no socket and keeps the answer honest.

Nothing here imports a transport

Not net/http, not the fasthttp fork, not testing. That is the whole point: this package is what the two sides agree on, so it cannot be allowed to prefer one of them.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Header struct{ Name, Value string }

Header is one name and value.

type Request

type Request struct {
	// Method defaults to GET.
	Method string
	// Target is the request target: a path with an optional query. It defaults
	// to "/". It is not a URL, because the host is the server's rather than the
	// test's.
	Target string
	// Header carries the request headers. Names are matched case-insensitively
	// on the way out, as HTTP requires.
	Header map[string][]string
	// Body is sent as-is. A test setting one usually sets Content-Type too;
	// nothing here guesses it, because a wrong guess would be a header the
	// handler branches on that the test did not write.
	Body []byte
}

Request describes one request to make.

The zero value is a GET of "/" with no headers and no body, because that is the request most tests want and spelling it out every time would bury the part that differs.

func (Request) ResolvedMethod

func (r Request) ResolvedMethod() string

ResolvedMethod is the method to send.

func (Request) ResolvedTarget

func (r Request) ResolvedTarget() string

ResolvedTarget is the target to send.

func (Request) SortedHeader

func (r Request) SortedHeader() []Header

SortedHeader returns the headers in a stable order, so a request built from a map produces the same bytes on both transports and a failure is reproducible.

type Response

type Response struct {
	Status int
	Header map[string][]string
	Body   []byte
}

Response is what a handler answered.

func (Response) Get

func (r Response) Get(name string) string

Get returns the first value of a response header, matched case-insensitively, or the empty string.

Case-insensitive because the two transports canonicalise header names differently — one gives X-Request-Id and the other X-Request-ID — and a test asserting on a header should not have to know which server answered it.

func (Response) Has

func (r Response) Has(name string) bool

Has reports whether a response header is present at all, which is the assertion for a header whose value is not the point.

func (Response) Text

func (r Response) Text() string

Text is the body as a string, which is what most assertions compare.

func (Response) Values

func (r Response) Values(name string) []string

Values returns every value of a response header, for the few headers that legitimately repeat — Set-Cookie above all.

type TestingT

type TestingT interface {
	Helper()
	Cleanup(func())
	Fatalf(string, ...any)
	Errorf(string, ...any)
}

TestingT is the minimal testing surface, the same one testutil accepts and for the same reason: a shipped package must not import testing.

It is declared here rather than in either transport's helper so both accept the same interface and a caller's own T wrapper satisfies both at once.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL