Skip to content

Commit d19222a

Browse files
GIT-62: Enable --dry-run mode
GIT-62: fix linter issues
1 parent 9156f4a commit d19222a

File tree

12 files changed

+388
-46
lines changed

12 files changed

+388
-46
lines changed

docs/design/dry-run-mode.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Dry Run Mode
2+
3+
As your test suits get bigger and complicated over the period of time, it is essential that the toolings used for creating tests provide an easy way to identify and list the tests being
4+
processed as part of your framework when invoked with certain arguments. And this listing needs
5+
to be quick and clean in order to enable quick turn around time of test development. This requirement bring in the need to introduce a `dry-run` behavior into the `e2e-framework`.
6+
7+
## Unit Of Test
8+
9+
Go treats each function starting with `Testxxx` as the Test unit. However, the same is not entirely true in case of the `e2e-framework`. This introduces dynamic tests that are generated during the runtime programmatically for each assessment of each feature.
10+
11+
From the perspective of the `e2e-framework`, the Unit of test is an `Assessment` that actually performs the assertion of an
12+
expected behavior or state of the system. These assessments are run as a sub-test of the main test identified by the function
13+
`Testxxx`. All framework specific behaviors built around this fundamental test unit of `Assessment`.
14+
15+
## Why not use `test.list` from `go test` ?
16+
17+
The `test.list` is a great way to run the dry-run equivalent behavior. However, it is not easily extendable into the core of `e2e-framework` as
18+
there are framework specific behavior such as `setup` and `teardown` workflows.
19+
20+
That, in conjunction with how the `test.list` works, it is not possible to extract information such as the `assessments` in the feature using the `test.list` mode brings the need to introduce a framework specific `dry-run` mode that can work well with `test.list` while providing all
21+
the framework specific benefits of how the Tests to be processed can be listed
22+
23+
## `--dry-run` mode
24+
`e2e-framework` adds a new CLI flag that can be used while invoking the test called `--dry-run`. This works in conjunction with `test.list` to provide the following behavior.
25+
26+
1. When the `--dry-run` mode is invoked No Setup/Teardown workflows are processed
27+
2. Will display the Assessments as individual tests like they would be processed if not invoked with `--dry-run` mode
28+
3. Skip all pre-post actions around the Before/After Features or Before/After Tests
29+
30+
When tests are invoked with `-test.list` argument, the `--dry-run` mode is automatically switched to enabled to make sure setup/teardown as well as the pre-post actions can be skipped.
31+
32+
## Example Output with `--dry-run`
33+
```bash
34+
❯ go test . -test.v -args --dry-run
35+
=== RUN TestPodBringUp
36+
=== RUN TestPodBringUp/Feature_One
37+
=== RUN TestPodBringUp/Feature_One/Create_Nginx_Deployment_1
38+
=== RUN TestPodBringUp/Feature_One/Wait_for_Nginx_Deployment_1_to_be_scaled_up
39+
=== RUN TestPodBringUp/Feature_Two
40+
=== RUN TestPodBringUp/Feature_Two/Create_Nginx_Deployment_2
41+
=== RUN TestPodBringUp/Feature_Two/Wait_for_Nginx_Deployment_2_to_be_scaled_up
42+
--- PASS: TestPodBringUp (0.00s)
43+
--- PASS: TestPodBringUp/Feature_One (0.00s)
44+
--- PASS: TestPodBringUp/Feature_One/Create_Nginx_Deployment_1 (0.00s)
45+
--- PASS: TestPodBringUp/Feature_One/Wait_for_Nginx_Deployment_1_to_be_scaled_up (0.00s)
46+
--- PASS: TestPodBringUp/Feature_Two (0.00s)
47+
--- PASS: TestPodBringUp/Feature_Two/Create_Nginx_Deployment_2 (0.00s)
48+
--- PASS: TestPodBringUp/Feature_Two/Wait_for_Nginx_Deployment_2_to_be_scaled_up (0.00s)
49+
PASS
50+
ok sigs.k8s.io/e2e-framework/examples/parallel_features 0.353s
51+
```
52+
53+
```bash
54+
❯ go test . -test.v -args --dry-run --assess "Deployment 1"
55+
=== RUN TestPodBringUp
56+
=== RUN TestPodBringUp/Feature_One
57+
=== RUN TestPodBringUp/Feature_One/Create_Nginx_Deployment_1
58+
=== RUN TestPodBringUp/Feature_One/Wait_for_Nginx_Deployment_1_to_be_scaled_up
59+
=== RUN TestPodBringUp/Feature_Two
60+
=== RUN TestPodBringUp/Feature_Two/Create_Nginx_Deployment_2
61+
env.go:425: Skipping assessment "Create Nginx Deployment 2": name not matched
62+
=== RUN TestPodBringUp/Feature_Two/Wait_for_Nginx_Deployment_2_to_be_scaled_up
63+
env.go:425: Skipping assessment "Wait for Nginx Deployment 2 to be scaled up": name not matched
64+
--- PASS: TestPodBringUp (0.00s)
65+
--- PASS: TestPodBringUp/Feature_One (0.00s)
66+
--- PASS: TestPodBringUp/Feature_One/Create_Nginx_Deployment_1 (0.00s)
67+
--- PASS: TestPodBringUp/Feature_One/Wait_for_Nginx_Deployment_1_to_be_scaled_up (0.00s)
68+
--- PASS: TestPodBringUp/Feature_Two (0.00s)
69+
--- SKIP: TestPodBringUp/Feature_Two/Create_Nginx_Deployment_2 (0.00s)
70+
--- SKIP: TestPodBringUp/Feature_Two/Wait_for_Nginx_Deployment_2_to_be_scaled_up (0.00s)
71+
PASS
72+
ok sigs.k8s.io/e2e-framework/examples/parallel_features 0.945s
73+
```
74+
75+
## Example with `-test.list`
76+
```bash
77+
❯ go test . -test.v -test.list ".*" -args
78+
TestPodBringUp
79+
ok sigs.k8s.io/e2e-framework/examples/parallel_features 0.645s
80+
```
81+
82+
As you can see from the above two examples, the output of the two commands are not really the same. Using `--dry-run` gives you a more framework specific behavior of how the tests are going to be processed in comparison to `-test.list`
83+

examples/dry_run/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Dry Run of Test Features
2+
3+
This directory contains the example of how to run the test features in `dry-run` mode using framework specific flags.
4+
5+
# Run Tests with flags
6+
7+
These test cases can be executed using the normal `go test` command by passing the right arguments
8+
9+
```bash
10+
go test -v . -args --dry-run
11+
```
12+
13+
With the output generated as following.
14+
15+
```bash
16+
=== RUN TestDryRunOne
17+
=== RUN TestDryRunOne/F1
18+
=== RUN TestDryRunOne/F1/Assessment_One
19+
=== RUN TestDryRunOne/F2
20+
=== RUN TestDryRunOne/F2/Assessment_One
21+
=== RUN TestDryRunOne/F2/Assessment_Two
22+
--- PASS: TestDryRunOne (0.00s)
23+
--- PASS: TestDryRunOne/F1 (0.00s)
24+
--- PASS: TestDryRunOne/F1/Assessment_One (0.00s)
25+
--- PASS: TestDryRunOne/F2 (0.00s)
26+
--- PASS: TestDryRunOne/F2/Assessment_One (0.00s)
27+
--- PASS: TestDryRunOne/F2/Assessment_Two (0.00s)
28+
=== RUN TestDryRunTwo
29+
=== RUN TestDryRunTwo/F1
30+
=== RUN TestDryRunTwo/F1/Assessment_One
31+
--- PASS: TestDryRunTwo (0.00s)
32+
--- PASS: TestDryRunTwo/F1 (0.00s)
33+
--- PASS: TestDryRunTwo/F1/Assessment_One (0.00s)
34+
PASS
35+
ok sigs.k8s.io/e2e-framework/examples/dry_run 0.618s
36+
```
37+
38+
Without the `--dry-run` mode you will see the additional log `Do not run this when in dry-run mode` getting printed onto your terminal.
39+
40+
In order to integrate this into the `test.list`, please run the following
41+
42+
```bash
43+
go test -v -list .
44+
```
45+
46+
Which generates the output as following
47+
48+
```bash
49+
TestDryRunOne
50+
TestDryRunTwo
51+
ok sigs.k8s.io/e2e-framework/examples/dry_run 0.375s
52+
```
53+
54+
To understand the difference in Output, please refer to the [Design Document](../../docs/design/dry-run-mode.md)

examples/dry_run/dry_run_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package dry_run
18+
19+
import (
20+
"context"
21+
"testing"
22+
23+
"k8s.io/klog/v2"
24+
"sigs.k8s.io/e2e-framework/pkg/envconf"
25+
"sigs.k8s.io/e2e-framework/pkg/features"
26+
)
27+
28+
func TestDryRunOne(t *testing.T) {
29+
f1 := features.New("F1").
30+
Assess("Assessment One", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
31+
// Perform Some assessment
32+
return ctx
33+
}).Feature()
34+
35+
f2 := features.New("F2").
36+
Setup(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
37+
klog.Info("Do not run this when in dry-run mode")
38+
return ctx
39+
}).
40+
Assess("Assessment One", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
41+
// Perform Some assessment
42+
return ctx
43+
}).
44+
Assess("Assessment Two", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
45+
// Perform Some assessment
46+
return ctx
47+
}).Feature()
48+
49+
testEnv.TestInParallel(t, f1, f2)
50+
}
51+
52+
func TestDryRunTwo(t *testing.T) {
53+
f1 := features.New("F1").
54+
Assess("Assessment One", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
55+
// Perform Some assessment
56+
return ctx
57+
}).Feature()
58+
59+
testEnv.Test(t, f1)
60+
}

examples/dry_run/main_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package dry_run
18+
19+
import (
20+
"os"
21+
"testing"
22+
23+
"sigs.k8s.io/e2e-framework/pkg/env"
24+
"sigs.k8s.io/e2e-framework/pkg/envconf"
25+
)
26+
27+
var (
28+
testEnv env.Environment
29+
)
30+
31+
func TestMain(m *testing.M) {
32+
cfg, _ := envconf.NewFromFlags()
33+
testEnv = env.NewWithConfig(cfg)
34+
35+
os.Exit(testEnv.Run(m))
36+
}

examples/parallel_features/parallel_features_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
appsv1 "k8s.io/api/apps/v1"
2525
corev1 "k8s.io/api/core/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27-
log "k8s.io/klog/v2"
2827

2928
"sigs.k8s.io/e2e-framework/klient/k8s"
3029
"sigs.k8s.io/e2e-framework/klient/wait"
@@ -43,7 +42,6 @@ var (
4342

4443
func TestMain(m *testing.M) {
4544
cfg, _ := envconf.NewFromFlags()
46-
log.InfoS("Args", "flag", cfg)
4745
testEnv = env.NewWithConfig(cfg)
4846

4947
clusterName = envconf.RandomName("kind-parallel", 16)

pkg/env/action.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"testing"
2323

24+
"k8s.io/klog/v2"
2425
"sigs.k8s.io/e2e-framework/pkg/envconf"
2526
"sigs.k8s.io/e2e-framework/pkg/internal/types"
2627
)
@@ -52,6 +53,10 @@ type action struct {
5253
func (a *action) runWithT(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
5354
switch a.role {
5455
case roleBeforeTest, roleAfterTest:
56+
if cfg.DryRunMode() {
57+
klog.V(2).Info("Skipping execution of roleBeforeTest and roleAfterTest due to framework being in dry-run mode")
58+
return ctx, nil
59+
}
5560
for _, f := range a.testFuncs {
5661
if f == nil {
5762
continue
@@ -74,6 +79,10 @@ func (a *action) runWithT(ctx context.Context, cfg *envconf.Config, t *testing.T
7479
func (a *action) runWithFeature(ctx context.Context, cfg *envconf.Config, t *testing.T, fi types.Feature) (context.Context, error) {
7580
switch a.role {
7681
case roleBeforeFeature, roleAfterFeature:
82+
if cfg.DryRunMode() {
83+
klog.V(2).Info("Skipping execution of roleBeforeFeature and roleAfterFeature due to framework being in dry-run mode")
84+
return ctx, nil
85+
}
7786
for _, f := range a.featureFuncs {
7887
if f == nil {
7988
continue
@@ -92,6 +101,10 @@ func (a *action) runWithFeature(ctx context.Context, cfg *envconf.Config, t *tes
92101
}
93102

94103
func (a *action) run(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
104+
if cfg.DryRunMode() {
105+
klog.V(2).InfoS("Skipping processing of action due to framework being in dry-run mode")
106+
return ctx, nil
107+
}
95108
for _, f := range a.funcs {
96109
if f == nil {
97110
continue

pkg/env/action_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func TestAction_Run(t *testing.T) {
3535
}{
3636
{
3737
name: "single-step action",
38+
cfg: &envconf.Config{},
3839
ctx: context.WithValue(context.TODO(), &ctxTestKeyString{}, 1),
3940
setup: func(ctx context.Context, cfg *envconf.Config) (val int, err error) {
4041
funcs := []types.EnvFunc{
@@ -50,6 +51,7 @@ func TestAction_Run(t *testing.T) {
5051
},
5152
{
5253
name: "multi-step action",
54+
cfg: &envconf.Config{},
5355
ctx: context.WithValue(context.TODO(), &ctxTestKeyString{}, 1),
5456
setup: func(ctx context.Context, cfg *envconf.Config) (val int, err error) {
5557
funcs := []types.EnvFunc{
@@ -69,6 +71,7 @@ func TestAction_Run(t *testing.T) {
6971
},
7072
{
7173
name: "read from context",
74+
cfg: &envconf.Config{},
7275
ctx: context.WithValue(context.TODO(), &ctxTestKeyString{}, 1),
7376
setup: func(ctx context.Context, cfg *envconf.Config) (val int, err error) {
7477
funcs := []types.EnvFunc{

0 commit comments

Comments
 (0)