framework

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2023 License: Apache-2.0 Imports: 41 Imported by: 0

README

e2e framework

Enables to easily build and start a number of automated test cases. Depends on ginkgo to describe test suites.

A sample usage is found in examples

Framework

Holds the global configurations for the framework. It mainly:

  1. *rest.Config Kubernetes client configuration
  2. context.Context a common context
  3. *zap.SugaredLogger a logger for test cases

etc.



import (
	"testing"

    // Adds test cases from other packages here
	_ "github.com/katanomi/pkg/examples/sample-e2e/another"
	"github.com/katanomi/pkg/testing/framework"
)

var fmw = framework.New("sample-e2e")

func TestMain(m *testing.M) {
	fmw.SynchronizedBeforeSuite(nil).
		SynchronizedAfterSuite(nil).
		MRun(m)
}

func TestE2E(t *testing.T) {
	// start step to run e2e
	fmw.Run(t)
}

Configuration

Each project e2e test may depend on some configurations. By default, if these configurations are missing, the test will not execute normally.

The framework has a built-in NewConfigCondition tool method to help us load and manage configurations. By default configuration files are stored in the katanomi-e2e namespace of the target cluster, and the name of the configmap will be prefixed with e2e-config.

func NewConfigCondition(configName string, obj interface{}) *configCondition {
	c := &configCondition{
		name: configName,
		obj:  obj,
	}

	return c
}

Of course, you can use environment variables to change these defaults:

E2E_CONFIG_NAMESPACE
E2E_CONFIG_NAME_PREFIX

TestCases

Most test cases can be written in a ginkgo fashion with a few helper methods to speedup construction and common logic. Cases can be started with:

  1. TestCase: constructor that receives an Options struct with all options for test case.
  2. P0Case: constructor method to set a name and a priority. Other levels are also available: P1Case, P2Case, P3Case.

After constructing a few more methods:

  1. WithFunc: takes a TestFunction that is given a context in which the test case executes.
  2. Do: finilizes the test case construction
package another

import (
	. "github.com/katanomi/pkg/testing/framework"
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)



var _ = TestCase(Options{Name: "Testinge2e", Priority: P0, Scope: NamespaceScoped}).WithFunc(func(ctx TestContext) {
	BeforeEach(func() {
		ctx.Debugw("some debug message")
		// fmt.Println("TestCase BeforeEach", ctx.Config)
	})
	It("should succeed", func() {
		Expect(ctx.Config).ToNot(BeNil())
	})
}).Do()

var _ = P1Case("another-test").Cluster().WithFunc(func(ctx TestContext) {
	// test case
	BeforeEach(func() {
		ctx.Debugw("before each in another pkg")
	})
	AfterEach(func() {
		ctx.Debugw("after each in another pkg")
	})
	Context("With a cluster scoped test case", func() {
		JustBeforeEach(func() {
			ctx.Infow("just before each in another pkg")
		})
		JustAfterEach(func() {
			ctx.Infow("just after each in another pkg")
		})
		It("it", func() {
			Expect(ctx.Config).ToNot(BeNil())
		})
	})
}).Do()

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConvertToAuthSecret added in v0.7.0

func ConvertToAuthSecret(auth client.Auth) (secret corev1.Secret)

ConvertToAuthSecret convert auth

func DurationToFloat

func DurationToFloat(dur time.Duration) float64

DurationToFloat converts a duration into a float64 seconds, useful for Ginkgo methods

func GetConfigFromContext added in v0.7.0

func GetConfigFromContext(ctx context.Context) interface{}

GetConfigFromContext get the config information from context

func GetDefaultEnv added in v0.7.0

func GetDefaultEnv(key string, defaultValue string) string

GetDefaultEnv get the parameter from env, if not set it use the defaultValue instead

func GetPluginAddress added in v0.7.0

func GetPluginAddress(client *resty.Client, plugin client.Interface) (address *duckv1.Addressable, err error)

GetPluginAddress get the base url of the plugin

func MustGetPluginAddress added in v0.7.0

func MustGetPluginAddress(client *resty.Client, plugin client.Interface) (address *duckv1.Addressable)

MustGetPluginAddress get the base url or panics if the parse fails.

func MustRollback added in v0.7.0

func MustRollback(testCtx *TestContext, obj client.Object, opts ...client.DeleteOption)

MustRollback delete an object and wait for completion

func NewConfigCondition added in v0.7.0

func NewConfigCondition(configName string, obj interface{}) *configCondition

NewConfigCondition construct an configCondition object `obj` is a pointer which used to unmarshal configuration to

func NewTestConfigMap added in v0.7.0

func NewTestConfigMap(name, namespace string, data map[string]string) *v1.ConfigMap

NewTestConfigMap helper function for constructing a new configmap

func RequestWrapAuthMeta added in v0.7.0

func RequestWrapAuthMeta(req *resty.Request, auth client.Auth, meta client.Meta) *resty.Request

RequestWrapAuthMeta wrap auth and meta information into http request

func ResourceTopConditionIsReadyEventually added in v0.7.0

func ResourceTopConditionIsReadyEventually(ctx *TestContext, obj client.Object, readyFuncs ...IsReadyCheckFunc) func(g Gomega) error

ResourceTopConditionIsReadyEventually generic function to check if a resource is ready resource type must implement GetTopLevelCondition() *apis.Condition function

func WaitRollback added in v0.7.0

func WaitRollback(testCtx *TestContext, obj client.Object)

WaitRollback Wait for the delete object behavior to complete

Types

type Condition added in v0.7.0

type Condition interface {
	Condition(testCtx *TestContext) error
}

Condition describe the conditions which the test must match

func NewNamespaceCondition added in v0.7.0

func NewNamespaceCondition(ns string) Condition

NewNamespaceCondition construct a namespace condition

type ConditionFunc added in v0.7.0

type ConditionFunc func(testCtx *TestContext) error

ConditionFunc helper function to wrapping condition

func (ConditionFunc) Condition added in v0.7.0

func (c ConditionFunc) Condition(testCtx *TestContext) error

Condition implement the Condition interface

type Framework

type Framework struct {
	Name string

	Config *rest.Config

	Scheme *runtime.Scheme

	Context context.Context

	*zap.SugaredLogger

	Output io.Writer

	InitTimeout time.Duration

	sync.Once
}

Framework base framework for running automated test cases

func New

func New(name string) *Framework

New sets a name to framework

func (*Framework) MRun

func (f *Framework) MRun(m *testing.M)

MRun main testing.M run

func (*Framework) Run

func (f *Framework) Run(t *testing.T)

Run start tests

func (*Framework) SynchronizedAfterSuite

func (f *Framework) SynchronizedAfterSuite(destroyFunc func()) *Framework

SynchronizedAfterSuite destroys the whole environment

func (*Framework) SynchronizedBeforeSuite

func (f *Framework) SynchronizedBeforeSuite(initFunc func()) *Framework

SynchronizedBeforeSuite basic before suite initialization

func (*Framework) WithScheme

func (f *Framework) WithScheme(scheme *runtime.Scheme) *Framework

WithScheme adds a scheme object to the framework

type IsReadyCheckFunc added in v0.7.0

type IsReadyCheckFunc func(g Gomega, obj client.Object) error

IsReadyCheckFunc additional function to check if object is ready in an Eventually context

 example:
   ```
   func(g Gomega, obj client.Object) error {
	  if obj.GetName() == "" {
		fmt.Errorf("should have a name")
	  }
      // or use g.Expect instead
      g.Expect(obj.GetName()).To(Equal(""))
	  return nil
   }
   ```

type NamespaceCondition added in v0.7.0

type NamespaceCondition struct {
	Namespace string
}

NamespaceCondition generate namespace for testing

func (*NamespaceCondition) Condition added in v0.7.0

func (t *NamespaceCondition) Condition(testCtx *TestContext) error

Condition implement the Condition interface Delete the namespace when it already exists, then create a new one. After the testing is completed, delete the namespace as well.

type Options

type Options struct {
	// Name oof the test case
	Name string
	// Priority of the test case
	Priority TestCasePriority
	// Scope defines what kind of permissions this test case needs
	Scope TestCaseScope
	// Labels used to filter test cases when executing testing
	Labels []string
	// Condition used to check condition before testing
	Conditions []Condition
	// TestContextOptions used to setup TestContext
	TestContextOptions []TestContextOption
}

Options options for TestCase

type Poller added in v0.7.0

type Poller struct {
	Interval time.Duration
	Timeout  time.Duration
}

Poller describe the configuration of Poller Interval: Indicates the inspection interval Timeout: Indicates the maximum time the check will last

func (Poller) Settings added in v0.7.0

func (p Poller) Settings() (interval, timeout time.Duration)

Settings get the configuration Default values will be used if no custom settings are made

type ReconcileCondition added in v0.7.0

type ReconcileCondition struct {
	*Poller
	// contains filtered or unexported fields
}

ReconcileCondition check if a controller is available

func NewReconcileCondition added in v0.7.0

func NewReconcileCondition(obj client.Object, objCheckFun func(obj client.Object) bool) *ReconcileCondition

NewReconcileCondition helper function for constructing a `ReconcileCondition` object

func (*ReconcileCondition) Condition added in v0.7.0

func (n *ReconcileCondition) Condition(testCtx *TestContext) error

Condition implement the Condition interface Apply an object and wait for reconciliation, then check the status via `objCheckFun`

func (*ReconcileCondition) WithPoller added in v0.7.0

func (n *ReconcileCondition) WithPoller(interval, timeout time.Duration) *ReconcileCondition

WithPoller customize poller settings

type ServicePortForward added in v0.7.0

type ServicePortForward struct {
	Namespace         string
	ServiceName       string
	ServicePortFilter func(ports []v1.ServicePort) int32
	// contains filtered or unexported fields
}

ServicePortForward describe the configuration of port forwarding

func NewServicePortForward added in v0.7.0

func NewServicePortForward(ns string, serviceName string) *ServicePortForward

NewServicePortForward construct a new ServicePortForward object

func (*ServicePortForward) Close added in v0.7.0

func (s *ServicePortForward) Close()

Close will stop the forwarder

func (*ServicePortForward) Forward added in v0.7.0

func (s *ServicePortForward) Forward(testCtx *TestContext) (restyClient *resty.Client, err error)

Forward setting a forwarder

type TestCaseBuilder

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

TestCaseBuilder builder for TestCases helps provide methods to construct

func P0Case

func P0Case(name string) *TestCaseBuilder

P0Case builds a P0 case

func P1Case

func P1Case(name string) *TestCaseBuilder

P1Case builds a P1 case

func P2Case

func P2Case(name string) *TestCaseBuilder

P2Case builds a P1 case

func P3Case

func P3Case(name string) *TestCaseBuilder

P3Case builds a P1 case

func TestCase

func TestCase(opts Options) *TestCaseBuilder

TestCase constructor for test cases

func (*TestCaseBuilder) Cluster

func (b *TestCaseBuilder) Cluster() *TestCaseBuilder

Cluster set the scope of the testcase as a cluster scoped

func (*TestCaseBuilder) Do

func (b *TestCaseBuilder) Do() bool

Do build and return the test case

func (*TestCaseBuilder) DoFunc added in v0.7.0

func (b *TestCaseBuilder) DoFunc(f TestFunction) bool

DoFunc build and return the test case, just like the Do function

func (*TestCaseBuilder) Namespaced

func (b *TestCaseBuilder) Namespaced() *TestCaseBuilder

Namespaced set the scope of the testcase as namespaced

func (*TestCaseBuilder) P0

P0 sets as P0

func (*TestCaseBuilder) P1

P1 sets as P1

func (*TestCaseBuilder) P2

P2 sets as P2

func (*TestCaseBuilder) P3

P3 sets as P3

func (*TestCaseBuilder) WithCondition added in v0.7.0

func (b *TestCaseBuilder) WithCondition(funcs ...Condition) *TestCaseBuilder

WithCondition sets conditions

func (*TestCaseBuilder) WithFunc

func (b *TestCaseBuilder) WithFunc(tc TestFunction) *TestCaseBuilder

WithFunc replaces the function with another given function

func (*TestCaseBuilder) WithLabels added in v0.7.0

func (b *TestCaseBuilder) WithLabels(labels ...string) *TestCaseBuilder

WithLabels sets labels

func (*TestCaseBuilder) WithPriority

func (b *TestCaseBuilder) WithPriority(prior TestCasePriority) *TestCaseBuilder

WithPriority sets priorities

func (*TestCaseBuilder) WithTestContextOptions added in v0.7.0

func (b *TestCaseBuilder) WithTestContextOptions(options ...TestContextOption) *TestCaseBuilder

WithTestContextOptions sets options of TestContext

type TestCaseLabel added in v0.7.0

type TestCaseLabel = string

TestCaseLabel label for test case

const (
	ControllerLabel TestCaseLabel = "controller"
	WebhookLabel    TestCaseLabel = "webhook"
	WebServiceLabel TestCaseLabel = "webservice"
	CliLabel        TestCaseLabel = "cli"
)

type TestCasePriority

type TestCasePriority uint16

TestCasePriority priority for the testcase

const (
	// P0 critical priority test case
	P0 TestCasePriority = 0
	// P1 high priority test case
	P1 TestCasePriority = 1
	// P2 medium priority test case
	P2 TestCasePriority = 2
	// P3 low priority test case
	P3 TestCasePriority = 3
)

type TestCaseScope

type TestCaseScope string

TestCaseScope scope for test case

const (
	// ClusterScoped cluster test case scope
	ClusterScoped TestCaseScope = "Cluster"
	// NamespaceScoped test case scoped for a Namespace
	NamespaceScoped TestCaseScope = "Namespaced"
)

type TestConfig added in v0.7.0

type TestConfig struct {
	Namespace string
	Name      string
	// contains filtered or unexported fields
}

TestConfig Provide a unified way to get configuration from configmap

func NewE2EConfig added in v0.7.0

func NewE2EConfig(cmName string) *TestConfig

NewE2EConfig construct a `TestConfig` with special configmap name

func (*TestConfig) GetConfig added in v0.7.0

func (c *TestConfig) GetConfig(ctx context.Context, clt client.Client) (string, error)

GetConfig get configuration by specified client

type TestContext

type TestContext struct {
	Context            context.Context
	Config             *rest.Config
	Client             client.Client
	MultiClusterClient multicluster.Interface
	*zap.SugaredLogger

	Namespace string

	Scheme *runtime.Scheme
}

TestContext a test context

type TestContextOption added in v0.7.0

type TestContextOption func(*TestContext)

TestContextOption options for TestContext

func NamespaceOption added in v0.7.0

func NamespaceOption(ns string) TestContextOption

NamespaceOption customize the namespace name

func NamespacePrefixOption added in v0.7.0

func NamespacePrefixOption(prefix string) TestContextOption

NamespacePrefixOption customize the prefix of the namespace name

type TestFunction

type TestFunction func(*TestContext)

TestFunction function used as describe

type TestNamespaceCondition added in v0.7.0

type TestNamespaceCondition struct{}

TestNamespaceCondition generate namespace for testing

func (*TestNamespaceCondition) Condition added in v0.7.0

func (t *TestNamespaceCondition) Condition(testCtx *TestContext) error

Condition implement the Condition interface Delete the namespace when it already exists, then create a new one. After the testing is completed, delete the namespace as well.

Jump to

Keyboard shortcuts

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