tasktest

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package tasktest is the conformance suite for contracts.Service, and a fake that passes it.

It exists because an interface is justified by a passing fake and not by a second production implementation (AGENTS.md rule 8). RunService is the specification of the lifecycle written as executable cases; the real service and the fake both run it, so "the fake behaves like the real thing" is a test result rather than a hope, and a consumer that tests against the fake is testing against the rules the database enforces.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RunService

func RunService(t *testing.T, h Harness)

RunService is the conformance suite. Every implementation of contracts.Service passes it, or it is not one.

Types

type Fake

type Fake struct {
	// contains filtered or unexported fields
}

Fake is contracts.Service over a map: the same rules, no database, no transaction. A consumer that wants to test what it does when a task is assigned takes one of these instead of a Postgres.

It ignores the transaction it is handed, and that is the honest limit of it: it cannot tell a caller that a write did not commit, because nothing here commits. Everything it can be wrong about is what RunService checks, and fake_test.go runs the whole suite against it.

func NewFake

func NewFake() *Fake

NewFake returns an empty store.

func (*Fake) Assign

func (f *Fake) Assign(_ context.Context, _ db.Tx[db.Tenant], id, assignee uuid.UUID) (*contracts.Task, error)

Assign mirrors internal.Service.Assign.

func (*Fake) CheckSLA

func (f *Fake) CheckSLA(_ context.Context, _ db.Tx[db.Tenant], id uuid.UUID) (*contracts.Task, error)

CheckSLA mirrors internal.Service.CheckSLA.

func (*Fake) Published

func (f *Fake) Published() []string

Published is the names of the events the fake would have emitted.

func (*Fake) Put

func (f *Fake) Put(task *contracts.Task) uuid.UUID

Put stores a task, giving it an id if it has none, and returns the id. It is the fake's stand-in for the create route.

func (*Fake) Resolve

func (f *Fake) Resolve(_ context.Context, _ db.Tx[db.Tenant], id uuid.UUID, resolution string) (*contracts.Task, error)

Resolve mirrors internal.Service.Resolve.

func (*Fake) Tasks

func (f *Fake) Tasks() map[uuid.UUID]contracts.Task

Tasks is every task the fake holds, for a consumer asserting on state rather than on a return value.

type Fixture

type Fixture struct {
	Ctx     context.Context
	Tx      db.Tx[db.Tenant]
	Service contracts.Service
	// Seed stores a task and returns the id it was given. It is the one thing
	// the suite cannot do through the interface, because the interface is the
	// lifecycle and creating a task is kit/rest's five routes.
	Seed func(*contracts.Task) uuid.UUID
	// Published is the events the implementation has published so far, in
	// order. The fake returns what it recorded; the real service's harness
	// reads the outbox rows its transaction has written.
	//
	// It is part of the fixture because half of what the lifecycle promises is
	// silence: every command is idempotent, and an idempotent command that
	// publishes is a subscriber told twice about one thing. A suite that could
	// only see return values could not check that, and it is the half a retry
	// exercises every day.
	Published func() []string
}

Fixture is one case's world: a Service, the transaction its commands take, and a store to put tasks in. The transaction is the real thing for the real service and the zero value for the fake, which never looks at it.

type Harness

type Harness func(t *testing.T, run func(Fixture))

Harness builds one Fixture and calls run with it. It is written this way round — the harness calling the case rather than returning to it — because the real service's fixture is a transaction, and a transaction is a scope somebody has to close: the harness wraps the case in db.Run and rolls back on the way out, which a Harness that only returned a Fixture could not do.

RunService calls it once per case, so no case sees another's rows.

Jump to

Keyboard shortcuts

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