contracts

package
v0.66.0 Latest Latest
Warning

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

Go to latest
Published: May 29, 2022 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package specs

Summary

This package implements generic CRUD operation related testing specifications that commonly appears upon interacting with external resources.

Reason for separate pkg from resources pkg

This package originally was part of the resources pkg, but package "testing" has side effects on import. In order to avoid force the import on the implementations, the specs had to be extracted into a separate package. Since testing#T.Run is heavily used, abstracting testing.T away is difficult.

Minimum Requirement from Resource point of view

In order to make this package work, you have to implement the TestMinimumRequirementsWithExampleEntities specification. Most of the other Resource specs specification depends on the Resource specs mentioned in the min requirement specification. Keep in mind, that you have no guarantee on your Resource content during test execution, because some specification may alter the content of the Resource (db), or delete from it. If you need specific data in the Resource you want to test with, you must ensure in the test execution that such Context is correctly provisioned, and after test execution, cleaned up. If you use such data-set in a external Resource that needs to be kept intact, I advise you to use separate environments for test execution and manual testing.

Requirement from Business Entities

This package depends on a fact that there is a string field ID in a business entity struct, or at least a tag `ext:"ID"`. This allows the package to create specifications that assumes, that the ID field links the EntityTypeName structure to an external Resource object. The Resource specs package doesn't care about the content of the ID string field, and don't have assumptions other than the existence of the field ID on a struct

Index

Constants

View Source
const ErrIDRequired frameless.Error = `` /* 174-byte string literal not displayed */

Variables

This section is empty.

Functions

This section is empty.

Types

type CRD

type CRD[T any, ID any] interface {
	frameless.Creator[T]
	frameless.Finder[T, ID]
	frameless.Deleter[ID]
}

CRD is the minimum requirements to write easily behavioral specification for a resource.

type Creator

type Creator[Ent any, ID any] struct {
	Subject func(testing.TB) CreatorSubject[Ent, ID]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (Creator[Ent, ID]) Benchmark

func (c Creator[Ent, ID]) Benchmark(b *testing.B)

func (Creator[Ent, ID]) Spec added in v0.43.1

func (c Creator[Ent, ID]) Spec(s *testcase.Spec)

func (Creator[T, ID]) Test

func (c Creator[T, ID]) Test(t *testing.T)

type CreatorPublisher

type CreatorPublisher[Ent, ID any] struct {
	Subject func(testing.TB) CreatorPublisherSubject[Ent, ID]
	Context func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (CreatorPublisher[Ent, ID]) Benchmark

func (c CreatorPublisher[Ent, ID]) Benchmark(b *testing.B)

func (CreatorPublisher[Ent, ID]) Spec

func (c CreatorPublisher[Ent, ID]) Spec(s *testcase.Spec)

func (CreatorPublisher[Ent, ID]) String added in v0.53.0

func (c CreatorPublisher[Ent, ID]) String() string

func (CreatorPublisher[Ent, ID]) Test

func (c CreatorPublisher[Ent, ID]) Test(t *testing.T)

type CreatorPublisherSubject

type CreatorPublisherSubject[Ent, ID any] interface {
	CRD[Ent, ID]
	frameless.CreatorPublisher[Ent]
}

type CreatorSubject added in v0.63.0

type CreatorSubject[Ent, ID any] CRD[Ent, ID]

type Deleter

type Deleter[Ent, ID any] struct {
	Subject func(testing.TB) DeleterSubject[Ent, ID]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (Deleter[Ent, ID]) Benchmark

func (c Deleter[Ent, ID]) Benchmark(b *testing.B)

func (Deleter[Ent, ID]) Spec added in v0.43.1

func (c Deleter[Ent, ID]) Spec(s *testcase.Spec)

func (Deleter[Ent, ID]) Test

func (c Deleter[Ent, ID]) Test(t *testing.T)

type DeleterPublisher

type DeleterPublisher[Ent, ID any] struct {
	Subject func(testing.TB) DeleterPublisherSubject[Ent, ID]
	Context func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (DeleterPublisher[Ent, ID]) Benchmark

func (c DeleterPublisher[Ent, ID]) Benchmark(b *testing.B)

func (DeleterPublisher[Ent, ID]) Spec added in v0.53.0

func (c DeleterPublisher[Ent, ID]) Spec(s *testcase.Spec)

func (DeleterPublisher[Ent, ID]) String added in v0.53.0

func (c DeleterPublisher[Ent, ID]) String() string

func (DeleterPublisher[Ent, ID]) Test

func (c DeleterPublisher[Ent, ID]) Test(t *testing.T)

type DeleterPublisherSubject

type DeleterPublisherSubject[Ent, ID any] interface {
	CRD[Ent, ID]
	frameless.DeleterPublisher[ID]
}

type DeleterSubject added in v0.63.0

type DeleterSubject[Ent, ID any] CRD[Ent, ID]

type FileSystem added in v0.64.0

type FileSystem struct {
	Subject func(testing.TB) frameless.FileSystem
}

func (FileSystem) Benchmark added in v0.64.0

func (c FileSystem) Benchmark(b *testing.B)

func (FileSystem) Spec added in v0.64.0

func (c FileSystem) Spec(s *testcase.Spec)

func (FileSystem) String added in v0.64.0

func (c FileSystem) String() string

func (FileSystem) Test added in v0.64.0

func (c FileSystem) Test(t *testing.T)

type FindOne

type FindOne[Ent, ID any] struct {
	Subject func(testing.TB) FinderSubject[Ent, ID]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
	// MethodName is the name of the test subject QueryOne method of this contract specification.
	MethodName string
	// ToQuery takes an entity ptr and returns with a closure that has the knowledge about how to query on the Subject resource to find the entity.
	//
	// By convention, any preparation action that affect the Storage must take place prior to returning the closure.
	// The QueryOne closure should only have the Method call with the already mapped values.
	// ToQuery will be evaluated in the beginning of the testing,
	// and executed after all the test Context preparation is done.
	ToQuery func(tb testing.TB, resource FinderSubject[Ent, ID], ent Ent) QueryOne[Ent]
	// Specify allow further specification describing for a given FindOne query function.
	// If none specified, this field will be ignored
	Specify func(testing.TB)
}

func (FindOne[Ent, ID]) Benchmark

func (c FindOne[Ent, ID]) Benchmark(b *testing.B)

func (FindOne[Ent, ID]) Spec

func (c FindOne[Ent, ID]) Spec(s *testcase.Spec)

func (FindOne[Ent, ID]) String added in v0.46.0

func (c FindOne[Ent, ID]) String() string

func (FindOne[Ent, ID]) Test

func (c FindOne[Ent, ID]) Test(t *testing.T)

type Finder

type Finder[Ent, ID any] struct {
	Subject func(testing.TB) FinderSubject[Ent, ID]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (Finder[Ent, ID]) Benchmark

func (c Finder[Ent, ID]) Benchmark(b *testing.B)

func (Finder[Ent, ID]) Spec

func (c Finder[Ent, ID]) Spec(s *testcase.Spec)

func (Finder[Ent, ID]) Test

func (c Finder[Ent, ID]) Test(t *testing.T)

type FinderSubject added in v0.63.0

type FinderSubject[Ent, ID any] CRD[Ent, ID]

type Interface

type Interface interface {
	testcase.Contract
	testcase.OpenContract
}

Interface represent a resource specification also known as "contract".

The main goal of a resource Spec is to introduce dependency injection pattern at logical level between consumers and suppliers. In other words any expectations from a consumer/interactor/use-case towards a used dependency should be defined in a contract. This allows architecture flexibility since the expectations not bound to a certain technology, but purely high level and as such can be implemented in various ways.

Using resource Spec also force the writer of the Spec to keep things at high level and only focus on the expected behavior, instead of going into implementation details.

type MetaAccessor added in v0.43.1

type MetaAccessor[Ent, ID, V any] struct {
	Subject func(testing.TB) MetaAccessorSubject[Ent, ID, V]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
	MakeV   func(testing.TB) V
}

func (MetaAccessor[Ent, ID, V]) Benchmark added in v0.43.1

func (c MetaAccessor[Ent, ID, V]) Benchmark(b *testing.B)

func (MetaAccessor[Ent, ID, V]) Spec added in v0.43.1

func (c MetaAccessor[Ent, ID, V]) Spec(s *testcase.Spec)

func (MetaAccessor[Ent, ID, V]) Test added in v0.43.1

func (c MetaAccessor[Ent, ID, V]) Test(t *testing.T)

type MetaAccessorBasic added in v0.43.1

type MetaAccessorBasic[V any] struct {
	Subject func(testing.TB) frameless.MetaAccessor
	MakeV   func(testing.TB) V
}

MetaAccessorBasic V is the value T type that can be set and looked up with frameless.MetaAccessor.

func (MetaAccessorBasic[V]) Benchmark added in v0.43.1

func (c MetaAccessorBasic[V]) Benchmark(b *testing.B)

func (MetaAccessorBasic[V]) Spec added in v0.43.1

func (c MetaAccessorBasic[V]) Spec(s *testcase.Spec)

func (MetaAccessorBasic[V]) Test added in v0.43.1

func (c MetaAccessorBasic[V]) Test(t *testing.T)

type MetaAccessorPublisher added in v0.43.1

type MetaAccessorPublisher[Ent any, ID any, V any] struct {
	Subject func(testing.TB) MetaAccessorSubject[Ent, ID, V]
	Context func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
	MakeV   func(testing.TB) V
}

func (MetaAccessorPublisher[Ent, ID, V]) Benchmark added in v0.43.1

func (c MetaAccessorPublisher[Ent, ID, V]) Benchmark(b *testing.B)

func (MetaAccessorPublisher[Ent, ID, V]) Spec added in v0.43.1

func (c MetaAccessorPublisher[Ent, ID, V]) Spec(s *testcase.Spec)

func (MetaAccessorPublisher[Ent, ID, V]) Test added in v0.43.1

func (c MetaAccessorPublisher[Ent, ID, V]) Test(t *testing.T)

type MetaAccessorSubject added in v0.43.1

type MetaAccessorSubject[Ent any, ID any, V any] struct {
	frameless.MetaAccessor
	Resource  CRD[Ent, ID]
	Publisher interface {
		frameless.CreatorPublisher[Ent]
		frameless.UpdaterPublisher[Ent]
		frameless.DeleterPublisher[ID]
	}
}

type OnePhaseCommitProtocol

type OnePhaseCommitProtocol[Ent, ID any] struct {
	Subject func(testing.TB) OnePhaseCommitProtocolSubject[Ent, ID]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (OnePhaseCommitProtocol[Ent, ID]) Benchmark

func (c OnePhaseCommitProtocol[Ent, ID]) Benchmark(b *testing.B)

func (OnePhaseCommitProtocol[Ent, ID]) Spec

func (c OnePhaseCommitProtocol[Ent, ID]) Spec(s *testcase.Spec)

func (OnePhaseCommitProtocol[Ent, ID]) Test

func (c OnePhaseCommitProtocol[Ent, ID]) Test(t *testing.T)

type OnePhaseCommitProtocolSubject

type OnePhaseCommitProtocolSubject[Ent, ID any] struct {
	Resource      CRD[Ent, ID]
	CommitManager frameless.OnePhaseCommitProtocol
}

type Publisher added in v0.41.0

type Publisher[Ent, ID any] struct {
	Subject func(testing.TB) PublisherSubject[Ent, ID]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (Publisher[Ent, ID]) Benchmark added in v0.41.0

func (c Publisher[Ent, ID]) Benchmark(b *testing.B)

func (Publisher[Ent, ID]) Spec added in v0.41.0

func (c Publisher[Ent, ID]) Spec(s *testcase.Spec)

func (Publisher[Ent, ID]) String added in v0.41.0

func (c Publisher[Ent, ID]) String() string

func (Publisher[Ent, ID]) Test added in v0.41.0

func (c Publisher[Ent, ID]) Test(t *testing.T)

type PublisherSubject added in v0.41.0

type PublisherSubject[Ent, ID any] interface {
	CRD[Ent, ID]
	frameless.CreatorPublisher[Ent]
	frameless.UpdaterPublisher[Ent]
	frameless.DeleterPublisher[ID]
}

type Purger added in v0.62.0

type Purger[Ent, ID any] struct {
	Subject func(testing.TB) PurgerSubject[Ent, ID]
	MakeEnt func(testing.TB) Ent
}

func (Purger[Ent, ID]) Benchmark added in v0.62.0

func (c Purger[Ent, ID]) Benchmark(b *testing.B)

func (Purger[Ent, ID]) Spec added in v0.62.0

func (c Purger[Ent, ID]) Spec(s *testcase.Spec)

func (Purger[Ent, ID]) Test added in v0.62.0

func (c Purger[Ent, ID]) Test(t *testing.T)

type PurgerSubject added in v0.62.0

type PurgerSubject[Ent, ID any] interface {
	CRD[Ent, ID]
	frameless.Purger
}

type QueryOne

type QueryOne[Ent any] func(tb testing.TB, ctx context.Context, ptr *Ent) (found bool, err error)

QueryOne is the generic representation of a query that meant to find one result. It is really similar to resources.Finder#FindByID, with the exception that the closure meant to know the query method name on the subject and the inputs it requires.

QueryOne is generated through ToQuery factory function in FindOne resource contract specification.

type Updater

type Updater[Ent any, ID any] struct {
	Subject func(testing.TB) UpdaterSubject[Ent, ID]
	MakeCtx func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

Updater will request an update for a wrapped entity object in the Resource

func (Updater[Ent, ID]) Benchmark

func (c Updater[Ent, ID]) Benchmark(b *testing.B)

func (Updater[Ent, ID]) Spec added in v0.43.1

func (c Updater[Ent, ID]) Spec(s *testcase.Spec)

func (Updater[Ent, ID]) Test

func (c Updater[Ent, ID]) Test(t *testing.T)

type UpdaterPublisher

type UpdaterPublisher[Ent, ID any] struct {
	Subject func(testing.TB) UpdaterPublisherSubject[Ent, ID]
	Context func(testing.TB) context.Context
	MakeEnt func(testing.TB) Ent
}

func (UpdaterPublisher[Ent, ID]) Benchmark

func (c UpdaterPublisher[Ent, ID]) Benchmark(b *testing.B)

func (UpdaterPublisher[Ent, ID]) Spec

func (c UpdaterPublisher[Ent, ID]) Spec(s *testcase.Spec)

func (UpdaterPublisher[Ent, ID]) String added in v0.53.0

func (c UpdaterPublisher[Ent, ID]) String() string

func (UpdaterPublisher[Ent, ID]) Test

func (c UpdaterPublisher[Ent, ID]) Test(t *testing.T)

type UpdaterPublisherSubject

type UpdaterPublisherSubject[Ent, ID any] interface {
	CRD[Ent, ID]
	frameless.Updater[Ent]
	frameless.UpdaterPublisher[Ent]
}

type UpdaterSubject

type UpdaterSubject[Ent any, ID any] interface {
	CRD[Ent, ID]
	frameless.Updater[Ent]
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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