testkit

package module
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Mar 26, 2024 License: MIT Imports: 24 Imported by: 0

README

Dogma Testing Toolkit

Blackbox testing utilities for Dogma applications.

Documentation Latest Version Build Status Code Coverage

The Dogma example application demonstrates how testkit can be used to test a Dogma application.

Documentation

Overview

Package testkit contains blackbox testing utilities for testing Dogma applications.

Index

Constants

This section is empty.

Variables

View Source
var IgnoreMessage = errors.New("this message does not need to be inspected by the predicate") //revive:disable-line:error-naming

IgnoreMessage is an error that can be returned by predicate functions to indicate that the predicate does not care about the message and therefore the predicate's result should not affect the expectation's result.

Functions

func DefaultMessageComparator added in v0.13.3

func DefaultMessageComparator(a, b dogma.Message) bool

DefaultMessageComparator returns true if a and b are considered equal.

It is the default implementation of the MessageComparator type.

It supports comparison of protocol buffers messages using the proto.Equal() function. All other types are compared using reflect.DeepEqual().

func InterceptCommandExecutor added in v0.13.5

func InterceptCommandExecutor(fn CommandExecutorInterceptor) interface {
	TestOption
	CallOption
}

InterceptCommandExecutor returns an option that causes fn to be called whenever a command is executed via the dogma.CommandExecutor returned by Test.CommandExecutor().

Intercepting calls to the command executor allows the user to simulate failures (or any other behavior) in the command executor.

Types

type Action added in v0.11.0

type Action interface {
	// Caption returns the caption that should be used for this action in the
	// test report.
	Caption() string

	// Location returns the location within the code that the action was
	// constructed.
	Location() location.Location

	// ConfigurePredicate updates o with any options required by the action.
	//
	// It is called before Do() when the action is used with Test.Expect().
	ConfigurePredicate(o *PredicateOptions)

	// Do performs the action within the context of a specific test.
	Do(ctx context.Context, s ActionScope) error
}

Action is an interface for any action that can be performed within a test.

Actions always attempt to cause some state change within the engine or application.

func AdvanceTime added in v0.11.0

func AdvanceTime(adj TimeAdjustment) Action

AdvanceTime returns an Action that simulates the passage of time by advancing the test's virtual clock.

This allows testing of application logic that depends on time, such as processes that use timeout messages and projections that use the "recorded at" time of events.

It accepts a TimeAdjustment which calculates the amount of time that the clock is advanced.

There are two built-in adjustment types; ToTime() and ByDuration(). Users may provide their own TimeAdjustment implementations that model time-related concepts within the application's business domain.

func Call added in v0.11.0

func Call(fn func(), options ...CallOption) Action

Call is an Action that invokes a user-defined function within the context of a test.

It is intended to execute application code that makes use of the dogma.CommandExecutor or dogma.EventRecorder interfaces. Typically this occurs in API handlers, where the "outside world" begins to interface with the Dogma application.

If a test does not need to involve such application code, use of the ExecuteCommand() and RecordEvent() actions is preferred.

Test implementations of these interfaces can be OBTAINED via the Test.CommandExecutor() and Test.EventRecorder() methods at any time; however, they may only be USED within a function invoked by a Call() action.

When Call() is used with Test.Expect() the expectation will match the messages dispatched via the test's executor and recorder, as well as those produced by handlers within the Dogma application.

func ExecuteCommand added in v0.11.0

func ExecuteCommand(m dogma.Message) Action

ExecuteCommand returns an Action that executes a command message.

func RecordEvent added in v0.11.0

func RecordEvent(m dogma.Message) Action

RecordEvent returns an Action that records an event message.

type ActionScope added in v0.11.0

type ActionScope struct {
	// App is the application being tested.
	App configkit.RichApplication

	// VirtualClock is the time that the Test uses as the engine time for the
	// NEXT Action.
	VirtualClock *time.Time

	// Engine is the engine used to handle messages.
	Engine *engine.Engine

	// Executor is the command executor returned by the Test's CommandExecutor()
	// method.
	Executor *CommandExecutor

	// OperationOptions is the set of options that should be used with calling
	// Engine.Dispatch() or Engine.Tick().
	OperationOptions []engine.OperationOption
}

ActionScope encapsulates the element's of a Test's state that may be inspected and manipulated by Action implementations.

type CallOption added in v0.13.5

type CallOption interface {
	// contains filtered or unexported methods
}

CallOption applies optional settings to a Call action.

type CommandExecutor added in v0.13.5

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

CommandExecutor is an implementation of dogma.CommandExecutor that executes commands within the context of a Test.

Each instance is bound to a particular Test. Use Test.CommandExecutor() to obtain an instance.

func (*CommandExecutor) Bind added in v0.13.5

func (e *CommandExecutor) Bind(eng *engine.Engine, options []engine.OperationOption)

Bind sets the engine and options used to execute commands.

It is intended for use within Action implementations that support executing commands outside of a Dogma handler, such as Call().

It must be called before ExecuteCommand(), otherwise ExecuteCommand() panics.

It must be accompanied by a call to Unbind() upon completion of the Action.

func (*CommandExecutor) ExecuteCommand added in v0.13.5

func (e *CommandExecutor) ExecuteCommand(
	ctx context.Context,
	m dogma.Message,
	_ ...dogma.ExecuteCommandOption,
) error

ExecuteCommand executes the command message m.

It panics unless it is called during an Action, such as when calling Test.Prepare() or Test.Expect().

func (*CommandExecutor) Intercept added in v0.13.5

Intercept installs an interceptor function that is invoked whenever ExecuteCommand() is called.

If fn is nil the interceptor is removed.

It returns the previous interceptor, if any.

func (*CommandExecutor) Unbind added in v0.13.5

func (e *CommandExecutor) Unbind()

Unbind removes the engine and options configured by a prior call to Bind().

Calls to ExecuteCommand() on an unbound executor will cause a panic.

type CommandExecutorInterceptor added in v0.13.5

type CommandExecutorInterceptor func(
	ctx context.Context,
	m dogma.Message,
	e dogma.CommandExecutor,
) error

CommandExecutorInterceptor is used by the InterceptCommandExecutor() option to specify custom behavior for the dogma.CommandExecutor returned by Test.CommandExecutor().

m is the command being executed.

e can be used to execute the command as it would be executed without this interceptor installed.

type Expectation added in v0.11.0

type Expectation interface {
	// Caption returns the caption that should be used for this action in the
	// test report.
	Caption() string

	// Predicate returns a new predicate that checks that this expectation is
	// satisfied.
	//
	// The predicate must be closed by calling Done() once the action it tests
	// is completed.
	Predicate(s PredicateScope) (Predicate, error)
}

An Expectation describes some criteria that may be met by an action.

func AllOf added in v0.11.0

func AllOf(children ...Expectation) Expectation

AllOf is an expectation that passes only if all of its children pass.

func AnyOf added in v0.11.0

func AnyOf(children ...Expectation) Expectation

AnyOf is an expectation that passes if any of its children pass.

func NoneOf added in v0.11.0

func NoneOf(children ...Expectation) Expectation

NoneOf is an expectation that passes only if all of its children fail.

func ToExecuteCommand added in v0.11.0

func ToExecuteCommand(m dogma.Message) Expectation

ToExecuteCommand returns an expectation that passes if a command is executed that is equal to m.

func ToExecuteCommandMatching added in v0.13.1

func ToExecuteCommandMatching(
	pred func(dogma.Message) error,
) Expectation

ToExecuteCommandMatching returns an expectation that passes if a command is executed that satisfies the given predicate function.

Always prefer using ToExecuteCommand() instead, if possible, as it provides more meaningful information in the result of a failure.

pred is the predicate function. It is called for each executed command. It must return nil at least once for the expectation to pass.

pred may return the IgnoreMessage error to indicate that the predicate does not apply to a specific message.

func ToExecuteCommandOfType added in v0.11.0

func ToExecuteCommandOfType(m dogma.Message) Expectation

ToExecuteCommandOfType returns an expectation that passes if a command of the same type as m is executed.

func ToOnlyExecuteCommandsMatching added in v0.13.2

func ToOnlyExecuteCommandsMatching(
	pred func(dogma.Message) error,
) Expectation

ToOnlyExecuteCommandsMatching returns an expectation that passes if all executed commands satisfy the given predicate function.

The expectation does NOT fail if other unrelated actions are performed, such as recording an event.

pred is the predicate function. It is called for each executed command. It must return nil (or IgnoreMessage) every time for the expectation to pass.

pred may return the IgnoreMessage error to indicate that the predicate does not apply to a specific message.

func ToOnlyRecordEventsMatching added in v0.13.2

func ToOnlyRecordEventsMatching(
	pred func(dogma.Message) error,
) Expectation

ToOnlyRecordEventsMatching returns an expectation that passes if all recorded events satisfy the given predicate function.

The expectation does NOT fail if other unrelated actions are performed, such as executing a command.

pred is the predicate function. It is called for each recorded event. It must return nil (or IgnoreMessage) every time for the expectation to pass.

pred may return the IgnoreMessage error to indicate that the predicate does not apply to a specific message.

func ToRecordEvent added in v0.11.0

func ToRecordEvent(m dogma.Message) Expectation

ToRecordEvent returns an expectation that passes if an event is recorded that is equal to m.

func ToRecordEventMatching added in v0.13.1

func ToRecordEventMatching(
	pred func(dogma.Message) error,
) Expectation

ToRecordEventMatching returns an expectation that passes if an event is recorded that satisfies the given predicate function.

Always prefer using ToRecordEvent() instead, if possible, as it provides more meaningful information in the result of a failure.

pred is the predicate function. It is called for each recorded event. It must return nil at least once for the expectation to pass.

pred may return the IgnoreMessage error to indicate that the predicate does not apply to a specific message.

func ToRecordEventOfType added in v0.11.0

func ToRecordEventOfType(m dogma.Message) Expectation

ToRecordEventOfType returns an expectation that passes if an event of the same type as m is recorded.

func ToRepeatedly added in v0.13.1

func ToRepeatedly(
	desc string,
	n int,
	f func(i int) Expectation,
) Expectation

ToRepeatedly is an expectation that repeats a fixed number of similar expectations.

desc is a human-readable description of the expectations. It should be phrased as an imperative statement, such as "debit a customer".

f is a factory function that produces the expectations. It is called n times. The parameter i indicates the current iteration starting with i == 0, until i == n-1. n must be 1 or greater.

func ToSatisfy added in v0.11.0

func ToSatisfy(
	desc string,
	pred func(*SatisfyT),
) Expectation

ToSatisfy returns an expectation that calls a function to check for arbitrary criteria.

desc is a human-readable description of the expectation. It should be phrased as an imperative statement, such as "debit the customer".

pred is a function that performs the expectation logic. It is passed a *SatisfyT, which is analogous to Go's *testing.T, and provides an almost identical interface.

type MessageComparator added in v0.13.3

type MessageComparator func(a, b dogma.Message) bool

A MessageComparator is a function that returns true if two messages are considered equal.

type Predicate added in v0.11.0

type Predicate interface {
	fact.Observer

	// Ok returns true if the expectation tested by this predicate has been met.
	//
	// The return value may change as the predicate is notified of additional
	// facts. It must return a consistent value once Done() has been called.
	Ok() bool

	// Done finalizes the predicate.
	//
	// The behavior of the predicate is undefined if it is notified of any
	// additional facts after Done() has been called, or if Done() is called
	// more than once.
	Done()

	// Report returns a report describing whether or not the expectation
	// was met.
	//
	// treeOk is true if the entire "tree" of expectations is considered to have
	// passed. This may not be the same value as returned from Ok() when this
	// expectation is used as a child of a composite expectation.
	//
	// The behavior of Report() is undefined if Done() has not been called.
	Report(treeOk bool) *Report
}

Predicate tests whether a specific Action satisfies an Expectation.

type PredicateOptions added in v0.11.0

type PredicateOptions struct {
	// MessageComparator is the comparator to use when testing two messages for
	// equality.
	MessageComparator MessageComparator

	// MatchDispatchCycleStartedFacts controls whether predicates that look for
	// specific messages should consider messages from DispatchCycleStarted
	// facts.
	//
	// If it is false, the predicate must only match against messages produced
	// by handlers.
	MatchDispatchCycleStartedFacts bool
}

PredicateOptions contains values that dictate how a predicate should behave.

type PredicateScope added in v0.11.0

type PredicateScope struct {
	// App is the application being tested.
	App configkit.RichApplication

	// Options contains values that dictate how the predicate should behave.
	// The options are provided by the Test and the Action being performed.
	Options PredicateOptions
}

PredicateScope encapsulates the element's of a Test's state that may be inspected by Predicate implementations.

type Report added in v0.11.0

type Report struct {
	// TreeOk is true if the "tree" that the expectation belongs to passed.
	TreeOk bool

	// Ok is true if this expectation passed.
	Ok bool

	// Criteria is a brief description of the expectation's requirement to pass.
	Criteria string

	// Outcome is a brief description of the outcome of the expectation.
	Outcome string

	// Explanation is a brief description of what actually happened during the
	// test as it relates to this expectation.
	Explanation string

	// Sections contains arbitrary "sections" that are added to the report by
	// the expectation.
	Sections []*ReportSection

	// SubReports contains the reports of any child expectations.
	SubReports []*Report
}

Report is a report on the outcome of an expectation.

func (*Report) Append added in v0.11.0

func (r *Report) Append(sr *Report)

Append adds sr as a sub-report of s.

func (*Report) Section added in v0.11.0

func (r *Report) Section(title string) *ReportSection

Section adds an arbitrary "section" to the report.

func (*Report) WriteTo added in v0.11.0

func (r *Report) WriteTo(next io.Writer) (_ int64, err error)

WriteTo writes the report to the given writer.

type ReportSection added in v0.11.0

type ReportSection struct {
	Title   string
	Content strings.Builder
}

ReportSection is a section of a report containing additional information about the expectation.

func (*ReportSection) Append added in v0.11.0

func (s *ReportSection) Append(f string, v ...any)

Append appends a line of text to the section's content.

func (*ReportSection) AppendListItem added in v0.11.0

func (s *ReportSection) AppendListItem(f string, v ...any)

AppendListItem appends a line of text prefixed with a bullet.

type SatisfyT added in v0.11.0

type SatisfyT struct {
	// Options contains the set of options that change the behavior of the
	// predicate function.
	//
	// They are not necessarily applicable to every predicate.
	Options PredicateOptions

	// Facts is an ordered slice of the facts that occurred.
	Facts []fact.Fact
	// contains filtered or unexported fields
}

SatisfyT is used within expectations made via ToSatisfy() to enforce the expectation.

It is analogous to the *testing.T type that is passed to tests in the native Go test runner.

func (*SatisfyT) Cleanup added in v0.11.0

func (t *SatisfyT) Cleanup(fn func())

Cleanup registers a function to be called when the test is complete. Cleanup functions will be called in last added, first called order.

func (*SatisfyT) Error added in v0.11.0

func (t *SatisfyT) Error(args ...any)

Error is equivalent to Log() followed by Fail().

func (*SatisfyT) Errorf added in v0.11.0

func (t *SatisfyT) Errorf(format string, args ...any)

Errorf is equivalent to Logf() followed by Fail().

func (*SatisfyT) Fail added in v0.11.0

func (t *SatisfyT) Fail()

Fail marks the function as having failed but continues execution.

func (*SatisfyT) FailNow added in v0.11.0

func (t *SatisfyT) FailNow()

FailNow marks the function as having failed and stops its execution.

func (*SatisfyT) Failed added in v0.11.0

func (t *SatisfyT) Failed() bool

Failed reports whether the test has failed.

func (*SatisfyT) Fatal added in v0.11.0

func (t *SatisfyT) Fatal(args ...any)

Fatal is equivalent to Log() followed by FailNow().

func (*SatisfyT) Fatalf added in v0.11.0

func (t *SatisfyT) Fatalf(format string, args ...any)

Fatalf is equivalent to Logf() followed by FailNow().

func (*SatisfyT) Helper added in v0.11.0

func (t *SatisfyT) Helper()

Helper marks the calling function as a test helper function.

func (*SatisfyT) Log added in v0.11.0

func (t *SatisfyT) Log(args ...any)

Log formats its arguments using default formatting, analogous to Println(), and records the text in the test report.

func (*SatisfyT) Logf added in v0.11.0

func (t *SatisfyT) Logf(format string, args ...any)

Logf formats its arguments according to the format, analogous to Printf(), and records the text in the test report.

func (*SatisfyT) Name added in v0.11.0

func (t *SatisfyT) Name() string

Name returns the name of the running test.

func (*SatisfyT) Parallel added in v0.11.0

func (t *SatisfyT) Parallel()

Parallel signals that this test is to be run in parallel with (and only with) other parallel tests.

It is a no-op in this implementation, but is included to increase compatibility with the *testing.T type.

func (*SatisfyT) Skip added in v0.11.0

func (t *SatisfyT) Skip(args ...any)

Skip is equivalent to Log() followed by SkipNow().

func (*SatisfyT) SkipNow added in v0.11.0

func (t *SatisfyT) SkipNow()

SkipNow marks the test as having been skipped and stops its execution.

func (*SatisfyT) Skipf added in v0.11.0

func (t *SatisfyT) Skipf(format string, args ...any)

Skipf is equivalent to Logf() followed by SkipNow().

func (*SatisfyT) Skipped added in v0.11.0

func (t *SatisfyT) Skipped() bool

Skipped reports whether the test was skipped.

type Test

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

Test contains the state of a single test.

func Begin added in v0.11.0

func Begin(
	t TestingT,
	app dogma.Application,
	options ...TestOption,
) *Test

Begin starts a new test.

func BeginContext added in v0.11.0

func BeginContext(
	ctx context.Context,
	t TestingT,
	app dogma.Application,
	options ...TestOption,
) *Test

BeginContext starts a new test within a context.

func (*Test) CommandExecutor added in v0.7.0

func (t *Test) CommandExecutor() dogma.CommandExecutor

CommandExecutor returns a dogma.CommandExecutor which can be used to execute commands within the context of this test.

The executor can be obtained at any time, but it can only be used within specific test actions.

Call() is the only built-in action that supports the command executor. It may be supported by other user-defined actions.

func (*Test) DisableHandlers added in v0.11.0

func (t *Test) DisableHandlers(names ...string) *Test

DisableHandlers disables a set of handlers by name.

By default all integration and projection handlers are disabled.

func (*Test) EnableHandlers added in v0.11.0

func (t *Test) EnableHandlers(names ...string) *Test

EnableHandlers enables a set of handlers by name.

By default all integration and projection handlers are disabled.

func (*Test) Expect added in v0.11.0

func (t *Test) Expect(act Action, e Expectation) *Test

Expect ensures that a single action results in some expected behavior.

func (*Test) Prepare

func (t *Test) Prepare(actions ...Action) *Test

Prepare performs a group of actions without making any expectations. It is used to place the application into a particular state.

type TestOption

type TestOption interface {
	// contains filtered or unexported methods
}

TestOption applies optional settings to a Test.

func StartTimeAt added in v0.11.0

func StartTimeAt(st time.Time) TestOption

StartTimeAt returns a test option that sets the initial time of the test's virtual clock.

By default, the current system time is used.

func WithMessageComparator added in v0.13.3

func WithMessageComparator(c MessageComparator) TestOption

WithMessageComparator returns a test option that sets the comparator to be used when comparing messages for equality.

This effects the ToExecuteCommand() and ToRecordEvent() expectations.

By default, DefaultMessageComparator is used.

func WithUnsafeOperationOptions added in v0.11.0

func WithUnsafeOperationOptions(options ...engine.OperationOption) TestOption

WithUnsafeOperationOptions returns a TestOption that applies a set of engine operation options when performing any action.

This function is provided for forward-compatibility with engine operations and for low level control of the engine's behavior.

The provided options may override options that the Test sets during its normal operation and should be used with caution.

type TestingT added in v0.6.0

type TestingT interface {
	Failed() bool
	Log(args ...any)
	Logf(f string, args ...any)
	Fatal(args ...any)
	FailNow()
	Helper()
}

TestingT is the interface via which the test framework consumes Go's *testing.T value.

It allows use of stand-ins, such as Ginkgo's GinkgoT() value.

type TimeAdjustment added in v0.11.0

type TimeAdjustment interface {
	// Description returns a human-readable string that describes how the clock
	// will be advanced.
	//
	// It should complete the sentence "The clock is being advanced...". For
	// example, "by 10 seconds".
	Description() string

	// Step returns the time that the virtual clock should be set to as a result
	// of the adjustment.
	//
	// t is the virtual clock's current time.
	Step(t time.Time) time.Time
}

A TimeAdjustment describes a change to the test's virtual clock.

func ByDuration added in v0.7.0

func ByDuration(d time.Duration) TimeAdjustment

ByDuration returns a TimeAdjustment that advances the virtual clock by a fixed duration.

func ToTime added in v0.7.0

func ToTime(t time.Time) TimeAdjustment

ToTime returns a TimeAdjustment that advances the virtual clock to a specific time.

Directories

Path Synopsis
Package engine contains an in-memory Dogma engine.
Package engine contains an in-memory Dogma engine.
internal/aggregate
Package aggregate provides engine components that handle messages that are routed to aggregate message handlers.
Package aggregate provides engine components that handle messages that are routed to aggregate message handlers.
internal/integration
Package integration provides engine components that handle messages that are routed to integration message handlers.
Package integration provides engine components that handle messages that are routed to integration message handlers.
internal/panicx
Package panicx contains utilities for providing meaningful contexts to panics that occur with the engine.
Package panicx contains utilities for providing meaningful contexts to panics that occur with the engine.
internal/process
Package process provides engine components that handle messages that are routed to process message handlers.
Package process provides engine components that handle messages that are routed to process message handlers.
internal/projection
Package projection provides engine components that handle messages that are routed to projection message handlers.
Package projection provides engine components that handle messages that are routed to projection message handlers.
Package envelope provides a container for passing Dogma messages and their meta-data between components.
Package envelope provides a container for passing Dogma messages and their meta-data between components.
Package fact contains structures that represents internal engine events.
Package fact contains structures that represents internal engine events.
internal
report
Package report builds human-readable reports that explain test results.
Package report builds human-readable reports that explain test results.
typecmp
Package typecmp compares Go types (not values).
Package typecmp compares Go types (not values).
Package location contains utilities for obtaining the function, file and line number of various Go types and values.
Package location contains utilities for obtaining the function, file and line number of various Go types and values.

Jump to

Keyboard shortcuts

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