func (e *testEnv) Test(t *testing.T, testFeatures ...types.Feature) {
	if e.ctx == nil {
		panic("context not set")  
	}
	if len(testFeatures) == 0 {
		t.Log("No test testFeatures provided, skipping test")
		return
	}
	beforeTestActions := e.getBeforeTestActions()
	var err error
	for _, action := range beforeTestActions {
		if e.ctx, err = action.runWithT(e.ctx, e.cfg, t); err != nil {
			t.Fatalf("BeforeEachTest failure: %s", err)
		}
	}
	beforeFeatureActions := e.getBeforeFeatureActions()
	afterFeatureActions := e.getAfterFeatureActions()
	for _, feature := range testFeatures {
		for _, action := range beforeFeatureActions {
			if e.ctx, err = action.runWithFeature(e.ctx, e.cfg, featureInfoFromFeature(feature)); err != nil {
				t.Fatalf("BeforeEachTest failure: %s", err)
			}
		}
		e.ctx = e.execFeature(e.ctx, t, feature)
		for _, action := range afterFeatureActions {
			if e.ctx, err = action.runWithFeature(e.ctx, e.cfg, featureInfoFromFeature(feature)); err != nil {
				t.Fatalf("BeforeEachTest failure: %s", err)
			}
		}
	}
	afterTestActions := e.getAfterTestActions()
	for _, action := range afterTestActions {
		if e.ctx, err = action.runWithT(e.ctx, e.cfg, t); err != nil {
			t.Fatalf("AfterEachTest failure: %s", err)
		}
	}
}
Test executes a feature test from within a TestXXX function.

Feature setups and teardowns are executed at the same *testing.T
contextual level as the "test" that invoked this method. Assessments
are executed as a subtests of the feature.  This approach allows
features/assessments to be filtered using go test -run flag.

Feature tests will have access to and able to update the context
passed to it.

BeforeTest and AfterTest operations are executed before and after
the feature is tested respectively.
package env
import (
	"context"
	"fmt"
	"log"
	"testing"
	"sigs.k8s.io/e2e-framework/pkg/envconf"
	"sigs.k8s.io/e2e-framework/pkg/features"
	"sigs.k8s.io/e2e-framework/pkg/internal/types"
)
type (
	Environment = types.Environment
	Func        = types.EnvFunc
	FeatureFunc = types.FeatureEnvFunc
	actionRole uint8
)
type testEnv struct {
	ctx     context.Context
	cfg     *envconf.Config
	actions []action
}
func New() types.Environment {
	return newTestEnv()
}
func NewWithConfig(cfg *envconf.Config) types.Environment {
	env := newTestEnv()
	env.cfg = cfg
	return env
}
func NewWithKubeConfig(kubeconfigfile string) types.Environment {
	env := newTestEnv()
	cfg := envconf.NewWithKubeConfig(kubeconfigfile)
	env.cfg = cfg
	return env
}
func NewInClusterConfig() types.Environment {
	env := newTestEnv()
	cfg := envconf.NewWithKubeConfig("")
	env.cfg = cfg
	return env
}
func NewWithContext(ctx context.Context, cfg *envconf.Config) (types.Environment, error) {
	if ctx == nil {
		return nil, fmt.Errorf("context is nil")
	}
	if cfg == nil {
		return nil, fmt.Errorf("environment config is nil")
	}
	return &testEnv{ctx: ctx, cfg: cfg}, nil
}
func newTestEnv() *testEnv {
	return &testEnv{
		ctx: context.Background(),
		cfg: envconf.New(),
	}
}
func (e *testEnv) WithContext(ctx context.Context) types.Environment {
	if ctx == nil {
		panic("nil context")  
	}
	env := &testEnv{
		ctx: ctx,
		cfg: e.cfg,
	}
	env.actions = append(env.actions, e.actions...)
	return env
}
func (e *testEnv) Setup(funcs ...Func) types.Environment {
	if len(funcs) == 0 {
		return e
	}
	e.actions = append(e.actions, action{role: roleSetup, funcs: funcs})
	return e
}
func (e *testEnv) BeforeEachTest(funcs ...types.TestEnvFunc) types.Environment {
	if len(funcs) == 0 {
		return e
	}
	e.actions = append(e.actions, action{role: roleBeforeTest, testFuncs: funcs})
	return e
}
func (e *testEnv) BeforeEachFeature(funcs ...FeatureFunc) types.Environment {
	if len(funcs) == 0 {
		return e
	}
	e.actions = append(e.actions, action{role: roleBeforeFeature, featureFuncs: funcs})
	return e
}
func (e *testEnv) AfterEachFeature(funcs ...FeatureFunc) types.Environment {
	if len(funcs) == 0 {
		return e
	}
	e.actions = append(e.actions, action{role: roleAfterFeature, featureFuncs: funcs})
	return e
}
func (e *testEnv) AfterEachTest(funcs ...types.TestEnvFunc) types.Environment {
	if len(funcs) == 0 {
		return e
	}
	e.actions = append(e.actions, action{role: roleAfterTest, testFuncs: funcs})
	return e
}