Documentation
¶
Overview ¶
Index ¶
- Constants
- Variables
- func BindingFunc(name string) any
- func BindingFuncs() map[string]any
- func RegisterBindings(rt *runner.Runtime)
- func RunSetup(ctx context.Context, suites []*Suite, out io.Writer) error
- func RunTeardown(ctx context.Context, suites []*Suite, out io.Writer) error
- func TestMain(m *testing.M)
- func WithWorker(ctx context.Context, id int) context.Context
- func WriteHTMLReport(w io.Writer, results []*TestResult) error
- func WriteJSONReport(w io.Writer, results []*TestResult) error
- type BindingRecord
- type Fixture
- func (f *Fixture) Coverage() *coverage.Collector
- func (f *Fixture) RootDir() string
- func (f *Fixture) Runs(r Runner) bool
- func (f *Fixture) SetAppRoot(root string, includes ...string)
- func (f *Fixture) SetCacheScope(scope string)
- func (f *Fixture) SetCoverage(c *coverage.Collector)
- func (f *Fixture) SetDatabase(provider model.DatabaseProvider)
- func (f *Fixture) SetRootFS(root fs.FS)
- type FixtureRequest
- type FixtureResponse
- type FixtureRunners
- type Record
- type Runner
- type Storage
- type Suite
- type TestResult
Examples ¶
Constants ¶
const ( CacheOff = "off" CacheWorker = "worker" )
Cache scopes, naming how far a parsed include and a compiled expression travel. The CLI spells them as --cache=off|worker.
const SuiteFile = config.VirtualHostConfigFile
SuiteFile is the file a directory of fixtures configures itself with. It is the same name an application root serves under, because it is the same file: a tree that is both a site and a suite writes one configuration, not two.
Variables ¶
var ErrFlatstackUnsupported = errors.New("program not supported by flatstack")
ErrFlatstackUnsupported reports that the flat bytecode compiler rejected the fixture's program. The fixture is skipped for the flatstack runner rather than delegated: a fallback run would report the compatibility interpreter's result and cost under the flatstack column.
ErrRunnerUnavailable reports that a runner cannot execute on this machine, which is a skip rather than a failure. The php runner returns it when no php binary is installed.
var Runners = []Runner{RunnerFlatstack, RunnerRuntime, RunnerPHP}
Runners lists every backend the test matrix covers, in report order.
Functions ¶
func BindingFunc ¶ added in v0.2.5
BindingFunc returns the raw (unregistered, unadapted) Go function behind a binding name, so benchmarks can measure the reflection return path on its own.
func BindingFuncs ¶ added in v0.2.5
BindingFuncs returns the example bindings keyed by the PHP name they are registered under.
func RegisterBindings ¶ added in v0.2.5
RegisterBindings installs the example bindings. It is passed to stdlib.Register as an extra installer, the same way a host contributes its own symbols.
func RunSetup ¶ added in v0.5.0
RunSetup runs the setup hooks of every suite, outermost first, and stops at the first failure. A suite whose state was not laid down has nothing for its fixtures to assert against, so the run fails before one executes rather than reporting the same missing table once per fixture.
func RunTeardown ¶ added in v0.5.0
RunTeardown runs the teardown hooks in reverse, whatever the fixtures did.
Every hook runs and every failure is reported, rather than the run stopping at the first: the suites are independent, and a caller learns about all of them instead of the one that happened to be innermost.
func WithWorker ¶ added in v0.5.0
WithWorker marks ctx as belonging to worker id, so a fixture run under it takes that worker's caches. The command's worker loop calls this once per goroutine; everything else inherits worker zero.
func WriteHTMLReport ¶ added in v0.2.1
func WriteHTMLReport(w io.Writer, results []*TestResult) error
WriteHTMLReport outputs an HTML report of the test results.
func WriteJSONReport ¶ added in v0.2.1
func WriteJSONReport(w io.Writer, results []*TestResult) error
WriteJSONReport outputs a JSON report of the test results.
Types ¶
type BindingRecord ¶ added in v0.2.5
BindingRecord is a plain Go struct handed to PHP as an object. Property access goes through runner.helperGet, which reads exported fields by reflection (case-insensitively), so `$r->name` and `$r->Name` both resolve.
func (BindingRecord) Label ¶ added in v0.2.5
func (r BindingRecord) Label() string
Label is an exported method so tests can exercise `$r->label()` dispatch on a forwarded Go value.
type Fixture ¶ added in v0.2.1
type Fixture struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Error string `yaml:"error"` // optional: expected uncaught error substring
Stdin string `yaml:"stdin"` // optional: top-level stdin contents
Options runner.Options `yaml:"options"` // optional: runtime options for both engines (memory_limit, ...)
Root string `yaml:"root"` // optional: include root, relative to the fixture's own directory
Serial bool `yaml:"serial"` // optional: do not overlap this fixture with peers in its area
Runner FixtureRunners `yaml:"runner"` // optional: runners the fixture opts out of
Request FixtureRequest `yaml:"request"`
Response FixtureResponse `yaml:"response"`
PHP string `yaml:"-"`
Expected string `yaml:"-"`
Path string `yaml:"-"`
// contains filtered or unexported fields
}
Fixture is the parsed representation of a .phpt test file.
func FindFixtures ¶ added in v0.2.1
FindFixtures locates all .phpt files in the specified paths (files or directories).
func ParseFixture ¶ added in v0.2.1
ParseFixture splits a .phpt file into its three sections and parses the YAML metadata.
func (*Fixture) Coverage ¶ added in v0.4.0
Coverage returns the collector installed with SetCoverage, or nil.
func (*Fixture) RootDir ¶ added in v0.3.3
RootDir returns the directory a fixture's includes resolve against. That is the directory holding it, which is also where the php runner executes, unless the fixture named another one with `root:`.
func (*Fixture) SetAppRoot ¶ added in v0.4.0
SetAppRoot points the fixture at the application root it runs under: the directory the test command was invoked in, or the suite root of the phpscript.yml governing the fixture. The autoload folder convention and the prelude includes resolve there, while the fixture's own relative includes keep resolving against its directory: runnerOptions layers the two, fixture directory first.
An include that is not there is not an error; the setting says what to load when the application provides it, and a tree without an autoload.php simply runs without one.
func (*Fixture) SetCacheScope ¶ added in v0.5.0
SetCacheScope says how far this fixture's parse caches reach.
The caches are what a suite trades memory for speed with. Worker, the default, gives each worker loop one set, reused by the fixtures that worker runs serially, so what is held scales with --parallel rather than with the number of fixtures. Off gives a run its own and drops them - and its runtime - when it ends, so a run is charged its own parsing and holds nothing afterwards.
func (*Fixture) SetCoverage ¶ added in v0.4.0
SetCoverage installs a statement-coverage collector for the fixture's runtime runner. Only that runner reports coverage: flatstack carries no coverage support, and the php runner is another process.
func (*Fixture) SetDatabase ¶ added in v0.5.0
func (f *Fixture) SetDatabase(provider model.DatabaseProvider)
SetDatabase names the connections this fixture's Database and Database\Migrate bindings resolve through. Nil leaves the binding on the process environment, which is what a fixture whose suite declared no env of its own has always had.
A suite passes the provider its setup hook applied the schema through, so the fixtures below it query the database the hook prepared rather than a second pool opened over the same DSN.
func (*Fixture) SetRootFS ¶ added in v0.3.3
SetRootFS binds the filesystem a fixture's includes resolve against. The directory holding the .phpt is the right answer for every caller: it is what the php runner uses as its working directory, so all three runners resolve a relative include to the same file.
type FixtureRequest ¶ added in v0.2.1
type FixtureRequest struct {
Args any `yaml:"args"` // map[string]string or []string or scalar
Get map[string]string `yaml:"get"`
Post map[string]string `yaml:"post"`
Cookie map[string]string `yaml:"cookie"`
Env map[string]string `yaml:"env"`
Headers map[string]string `yaml:"headers"`
Stdin string `yaml:"stdin"`
Body string `yaml:"body"`
}
FixtureRequest contains request data exposed to PHP as superglobals.
type FixtureResponse ¶ added in v0.2.1
FixtureResponse contains expected response assertions.
type FixtureRunners ¶ added in v0.3.0
FixtureRunners opts a fixture out of individual runners. An absent field means the runner is used; the default runtime can not be opted out of because it defines the fixture's expected output.
type Record ¶
Record is a rich value type returned to PHP. Its exported fields are read from PHP via property access (`$rec->key`, `$rec->value`), matched case-insensitively.
type Runner ¶ added in v0.3.0
type Runner string
Runner names an execution backend a fixture can be checked against.
const ( // RunnerFlatstack executes the fixture through the flat bytecode runtime, // which falls back to the compatibility interpreter for unsupported syntax. RunnerFlatstack Runner = "flatstack" // RunnerRuntime executes the fixture through the default interpreter. RunnerRuntime Runner = "runtime" // RunnerPHP executes the fixture through the php binary found in PATH. RunnerPHP Runner = "php" )
type Storage ¶
type Storage interface {
Set(ctx context.Context, key, value string)
Get(ctx context.Context, key string) (Record, error)
All(ctx context.Context) ([]Record, error)
Len() int64
Tenant() string
}
Storage is a host-provided key/value capability whose context parameters are supplied automatically when PHP invokes its methods.
Example ¶
ctx := context.WithValue(context.Background(), tenantKey, "acme")
storage, err := NewStorage(ctx)
if err != nil {
fmt.Println(err)
return
}
storage.Set(ctx, "color", "blue")
record, err := storage.Get(ctx, "color")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(storage.Tenant())
fmt.Println(record.Key, record.Value)
fmt.Println(storage.Len())
Output: acme color blue 1
func NewFailStorage ¶
NewFailStorage is a constructor that always fails, used to exercise the thrown-error path of `new`.
type Suite ¶ added in v0.5.0
type Suite struct {
// Dir is the suite root as the caller spells it, which is what an error
// names and what stdlib.RegisterFS is rooted at.
Dir string
// Config is the file read over the configuration the run started with.
Config config.Config
// Declared holds the keys the file itself named, so a caller can tell a
// setting the suite asked for from one it inherited.
Declared map[string]any
// contains filtered or unexported fields
}
Suite is one phpscript.yml governing the fixtures below the directory holding it: the connections they resolve, the prelude they load, and the hooks the session runs around them.
The provider is built once and held, because the setup hook and the fixtures have to share a pool. Two providers over one DSN are two pool caches, and a schema applied through the first is not in the database the second queries when the DSN names no shared file.
func LoadSuite ¶ added in v0.5.0
LoadSuite reads dir/phpscript.yml off disk over base, and returns nil when the directory holds no such file. A directory without one is not a suite root; it is a folder of fixtures that configures nothing.
forbidden refuses the keys that describe a whole run rather than one folder. It is false for the configuration found at or above the invocation root, which is the run's own, and true for one discovered below it.
func LoadSuiteFS ¶ added in v0.5.0
LoadSuiteFS is LoadSuite over a directory inside root, for a tree that is not on disk. The embedded fixtures the Go tests run are read this way.
func (*Suite) Include ¶ added in v0.5.0
Include is the prelude the fixtures below this suite root load, or "".
func (*Suite) Provider ¶ added in v0.5.0
func (s *Suite) Provider() model.DatabaseProvider
Provider answers the connections the fixtures below this suite root resolve.
A suite that declared no env of its own resolves what the run does, which is the process environment: a folder that named no connections is not asking for a set of its own. A suite that declared one gets only what it named, the rule a virtual host is already held to, so a fixture cannot reach a database its folder did not configure.
func (*Suite) RunHook ¶ added in v0.5.0
RunHook executes one hook file on a runtime carrying what a fixture below this suite root carries: the standard library rooted at the suite, the host bindings the fixtures use, and the suite's own connections.
The suite root is the runtime's filesystem, so a hook names its migrations the way an application does, relative to itself. Output goes to out, which a caller not reporting the hook may discard.
type TestResult ¶ added in v0.2.1
type TestResult struct {
Name string `json:"name"`
Description string `json:"description"`
Path string `json:"path"`
Passed bool `json:"passed"`
DurationMs int64 `json:"duration_ms"`
FailureReason string `json:"failure_reason,omitempty"`
GotOutput string `json:"got_output,omitempty"`
WantOutput string `json:"want_output,omitempty"`
Error string `json:"error,omitempty"`
Runner Runner `json:"runner,omitempty"`
Skipped bool `json:"skipped,omitempty"`
}
TestResult carries execution outcome for a single fixture.
func RunFixture ¶ added in v0.2.1
func RunFixture(ctx context.Context, f *Fixture) *TestResult
RunFixture executes a single fixture against the default runtime.
func RunFixtureOn ¶ added in v0.3.0
func RunFixtureOn(ctx context.Context, f *Fixture, r Runner) *TestResult
RunFixtureOn executes a single fixture against one runner. Every runner is held to the same expected output; the runner only decides how the source is executed.