Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix every_test_custom_ns test example #253

Merged
merged 1 commit into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions examples/every_test_custom_ns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ a custom namespace for every test. This could easily be done for every
feature as well if that is your preference.

First, you'll have to set up the env. In this example we assume an in-cluster configuration.

```go
var testenv env.Environment

func TestMain(m *testing.M) {
testenv = env.New()
...
testenv = env.New()
...
}
```

Second, set the BeforeEachTest hook to create the namespace. We store it in the
context so that it can be looked up on a per-test basis for deletion.

```go
testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return createNSForTest(ctx,cfg,t,runID)
Expand All @@ -23,7 +26,9 @@ testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing
// The creation uses the typical c.Resources() object.
cfg.Client().Resources().Create(ctx,&nsObj)
```

Third, set the AfterEachTest hook to lookup and delete the namespace.

```go
testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return deleteNSForTest(ctx,cfg,t,runID)
Expand All @@ -33,23 +38,30 @@ testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.
cfg.Client().Resources().Delete(ctx,&nsObj)
```

Forth, in your test you can lookup the namespace and casting to a string

```go
namespace := ctx.Value(GetNamespaceKey(t)).(string)
```

So, tying it all together, the `TestMain` looks like this:

```go
func TestMain(m *testing.M) {
testenv = env.New()
testenv = env.New()

// Specifying a run ID so that multiple runs wouldn't collide.
runID := envconf.RandomName("", 4)
// Specifying a run ID so that multiple runs wouldn't collide.
runID := envconf.RandomName("", 4)

/* Skipping cluster creation for brevity */
testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return createNSForTest(ctx, cfg, t, runID)
})
testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return deleteNSForTest(ctx, cfg, t, runID)
})
/* Skipping cluster creation for brevity */
testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return createNSForTest(ctx, cfg, t, runID)
})
testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return deleteNSForTest(ctx, cfg, t, runID)
})

os.Exit(testenv.Run(m))
os.Exit(testenv.Run(m))
}
```
```
10 changes: 4 additions & 6 deletions examples/every_test_custom_ns/k8s_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,14 @@ import (

func TestListPods(t *testing.T) {
f := features.New("pod list").
Assess("pods from kube-system", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
Assess("pods from namespace", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
var pods corev1.PodList
err := cfg.Client().Resources("kube-system").List(context.TODO(), &pods)
namespace := ctx.Value(GetNamespaceKey(t)).(string)
err := cfg.Client().Resources(namespace).List(context.TODO(), &pods)
if err != nil {
t.Fatal(err)
}
t.Logf("found %d pods", len(pods.Items))
if len(pods.Items) == 0 {
t.Fatal("no pods in namespace kube-system")
}
t.Logf("found %d pods in namespace %s", len(pods.Items), namespace)
return ctx
})

Expand Down
26 changes: 20 additions & 6 deletions examples/every_test_custom_ns/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"os"
"strings"
"testing"
"time"

Expand All @@ -29,6 +30,9 @@ import (
"sigs.k8s.io/e2e-framework/support/kind"
)

type NamespaceCtxKey string
type ClusterCtxKey string
maruina marked this conversation as resolved.
Show resolved Hide resolved

var testenv env.Environment

func TestMain(m *testing.M) {
Expand All @@ -53,11 +57,14 @@ func TestMain(m *testing.M) {
cfg.WithKubeconfigFile(kubeconfig)

// propagate cluster value
return context.WithValue(ctx, "cluster", cluster), nil
return context.WithValue(ctx, ClusterCtxKey("cluster"), cluster), nil
}).Finish(
// Teardown func: delete kind cluster
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
cluster := ctx.Value("cluster").(*kind.Cluster) // nil should be tested
cluster := ctx.Value(ClusterCtxKey("cluster")).(*kind.Cluster) // nil should be tested
if cluster == nil {
return ctx, fmt.Errorf("error getting kind cluster from context")
}
if err := cluster.Destroy(); err != nil {
return ctx, err
}
Expand All @@ -79,7 +86,7 @@ func TestMain(m *testing.M) {
// so that the deleteNSForTest routine can look it up and delete it.
func createNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, runID string) (context.Context, error) {
ns := envconf.RandomName(runID, 10)
ctx = context.WithValue(ctx, nsKey(t), ns)
ctx = context.WithValue(ctx, GetNamespaceKey(t), ns)

t.Logf("Creating NS %v for test %v", ns, t.Name())
nsObj := v1.Namespace{}
Expand All @@ -89,14 +96,21 @@ func createNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, run

// DeleteNSForTest looks up the namespace corresponding to the given test and deletes it.
func deleteNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, runID string) (context.Context, error) {
ns := fmt.Sprint(ctx.Value(nsKey(t)))
ns := fmt.Sprint(ctx.Value(GetNamespaceKey(t)))
t.Logf("Deleting NS %v for test %v", ns, t.Name())

nsObj := v1.Namespace{}
nsObj.Name = ns
return ctx, cfg.Client().Resources().Delete(ctx, &nsObj)
}

func nsKey(t *testing.T) string {
return "NS-for-%v" + t.Name()
// GetNamespaceKey returns the context key for a given test
func GetNamespaceKey(t *testing.T) NamespaceCtxKey {
// When we pass t.Name() from inside an `assess` step, the name is in the form TestName/Features/Assess
if strings.Contains(t.Name(), "/") {
return NamespaceCtxKey(strings.Split(t.Name(), "/")[0])
}
Comment on lines +110 to +112
Copy link
Contributor Author

@maruina maruina May 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed because when we call t.Name() from inside an Assess the name is TestName/Features/Assess.

When we call if from inside testenv.BeforeEachTest the name is just TestName

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @maruina make sure to add a comment to function GetNamespaceKey with your explanation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this better?


// When pass t.Name() from inside a `testenv.BeforeEachTest` function, the name is just TestName
return NamespaceCtxKey(t.Name())
}