Skip to content

Commit 2917763

Browse files
authored
Refactor unit test framework (#705)
1 parent a2b3516 commit 2917763

File tree

6 files changed

+523
-132
lines changed

6 files changed

+523
-132
lines changed

controllers/ibmpowervscluster_controller_test.go

Lines changed: 106 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,126 @@ limitations under the License.
1717
package controllers
1818

1919
import (
20-
"context"
20+
"fmt"
21+
"testing"
22+
"time"
2123

24+
. "github.com/onsi/gomega"
25+
corev1 "k8s.io/api/core/v1"
2226
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2327
"k8s.io/klog/v2/klogr"
2428
ctrl "sigs.k8s.io/controller-runtime"
2529
"sigs.k8s.io/controller-runtime/pkg/client"
2630

2731
infrav1beta1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta1"
28-
29-
. "github.com/onsi/ginkgo"
30-
. "github.com/onsi/gomega"
32+
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
33+
"sigs.k8s.io/cluster-api/util"
3134
)
3235

33-
var _ = Describe("IBMPowerVSClusterReconciler", func() {
34-
35-
Context("Reconcile an IBMMPowerVSCluster", func() {
36-
It("should not error and not requeue the request", func() {
37-
ctx := context.Background()
36+
func TestIBMPowerVSClusterReconciler(t *testing.T) {
37+
testCases := []struct {
38+
name string
39+
powervsCluster *infrav1beta1.IBMPowerVSCluster
40+
ownerCluster *capiv1beta1.Cluster
41+
expectError bool
42+
}{
43+
{
44+
name: "Should fail Reconcile if owner cluster not found",
45+
powervsCluster: &infrav1beta1.IBMPowerVSCluster{ObjectMeta: metav1.ObjectMeta{GenerateName: "powervs-test-", OwnerReferences: []metav1.OwnerReference{
46+
{
47+
APIVersion: capiv1beta1.GroupVersion.String(),
48+
Kind: "Cluster",
49+
Name: "capi-test",
50+
UID: "1",
51+
}}},
52+
Spec: infrav1beta1.IBMPowerVSClusterSpec{ServiceInstanceID: "foo"}},
53+
expectError: true,
54+
},
55+
{
56+
name: "Should not reconcile if owner reference is not set",
57+
powervsCluster: &infrav1beta1.IBMPowerVSCluster{ObjectMeta: metav1.ObjectMeta{GenerateName: "powervs-test-"}, Spec: infrav1beta1.IBMPowerVSClusterSpec{ServiceInstanceID: "foo"}},
58+
expectError: false,
59+
},
60+
{
61+
name: "Should Reconcile successfully if no IBMPowerVSCluster found",
62+
expectError: false,
63+
},
64+
}
3865

66+
for _, tc := range testCases {
67+
t.Run(tc.name, func(t *testing.T) {
68+
g := NewWithT(t)
3969
reconciler := &IBMPowerVSClusterReconciler{
40-
Client: k8sClient,
70+
Client: testEnv.Client,
4171
Log: klogr.New(),
4272
}
4373

44-
instance := &infrav1beta1.IBMPowerVSCluster{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}, Spec: infrav1beta1.IBMPowerVSClusterSpec{ServiceInstanceID: "foo"}}
74+
ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("namespace-%s", util.RandomString(5)))
75+
g.Expect(err).To(BeNil())
4576

46-
// Create the IBMPowerVSCluster object and expect the Reconcile to be created
47-
Expect(k8sClient.Create(ctx, instance)).To(Succeed())
48-
defer func() {
49-
err := k8sClient.Delete(ctx, instance)
50-
Expect(err).NotTo(HaveOccurred())
51-
}()
77+
if tc.ownerCluster != nil {
78+
tc.ownerCluster.Namespace = ns.Name
79+
g.Expect(testEnv.Create(ctx, tc.ownerCluster)).To(Succeed())
80+
defer func(do ...client.Object) {
81+
g.Expect(testEnv.Cleanup(ctx, do...)).To(Succeed())
82+
}(tc.ownerCluster)
83+
tc.powervsCluster.OwnerReferences = []metav1.OwnerReference{
84+
{
85+
APIVersion: capiv1beta1.GroupVersion.String(),
86+
Kind: "Cluster",
87+
Name: tc.ownerCluster.Name,
88+
UID: "1",
89+
},
90+
}
91+
}
92+
createCluster(g, tc.powervsCluster, ns.Name)
93+
defer cleanupCluster(g, tc.powervsCluster, ns)
5294

53-
result, err := reconciler.Reconcile(ctx, ctrl.Request{
54-
NamespacedName: client.ObjectKey{
55-
Namespace: instance.Namespace,
56-
Name: instance.Name,
57-
},
58-
})
59-
Expect(err).NotTo(HaveOccurred())
60-
Expect(result.RequeueAfter).To(BeZero())
61-
Expect(result.Requeue).To(BeFalse())
95+
if tc.powervsCluster != nil {
96+
_, err := reconciler.Reconcile(ctx, ctrl.Request{
97+
NamespacedName: client.ObjectKey{
98+
Namespace: tc.powervsCluster.Namespace,
99+
Name: tc.powervsCluster.Name,
100+
},
101+
})
102+
if tc.expectError {
103+
g.Expect(err).ToNot(BeNil())
104+
} else {
105+
g.Expect(err).To(BeNil())
106+
}
107+
} else {
108+
_, err := reconciler.Reconcile(ctx, ctrl.Request{
109+
NamespacedName: client.ObjectKey{
110+
Namespace: ns.Name,
111+
Name: "test",
112+
},
113+
})
114+
g.Expect(err).To(BeNil())
115+
}
62116
})
63-
})
64-
})
117+
}
118+
}
119+
120+
func createCluster(g *WithT, powervsCluster *infrav1beta1.IBMPowerVSCluster, namespace string) {
121+
if powervsCluster != nil {
122+
powervsCluster.Namespace = namespace
123+
g.Expect(testEnv.Create(ctx, powervsCluster)).To(Succeed())
124+
g.Eventually(func() bool {
125+
cluster := &infrav1beta1.IBMPowerVSCluster{}
126+
key := client.ObjectKey{
127+
Name: powervsCluster.Name,
128+
Namespace: namespace,
129+
}
130+
err := testEnv.Get(ctx, key, cluster)
131+
return err == nil
132+
}, 10*time.Second).Should(Equal(true))
133+
}
134+
}
135+
136+
func cleanupCluster(g *WithT, powervsCluster *infrav1beta1.IBMPowerVSCluster, namespace *corev1.Namespace) {
137+
if powervsCluster != nil {
138+
func(do ...client.Object) {
139+
g.Expect(testEnv.Cleanup(ctx, do...)).To(Succeed())
140+
}(powervsCluster, namespace)
141+
}
142+
}

controllers/ibmpowervsmachine_controller_test.go

Lines changed: 0 additions & 55 deletions
This file was deleted.

controllers/suite_test.go

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,63 +17,76 @@ limitations under the License.
1717
package controllers
1818

1919
import (
20-
"path/filepath"
20+
"fmt"
21+
"path"
2122
"testing"
2223

23-
// +kubebuilder:scaffold:imports
24-
"github.com/onsi/ginkgo/reporters"
24+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2525
"k8s.io/client-go/kubernetes/scheme"
26-
"k8s.io/client-go/rest"
27-
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
28-
"sigs.k8s.io/controller-runtime/pkg/client"
29-
"sigs.k8s.io/controller-runtime/pkg/envtest"
26+
ctrl "sigs.k8s.io/controller-runtime"
3027

28+
// +kubebuilder:scaffold:imports
3129
infrav1beta1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta1"
32-
33-
. "github.com/onsi/ginkgo"
34-
. "github.com/onsi/gomega"
30+
"sigs.k8s.io/cluster-api-provider-ibmcloud/test/helpers"
31+
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
3532
)
3633

37-
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
38-
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
39-
40-
var cfg *rest.Config
41-
var k8sClient client.Client
42-
var testEnv *envtest.Environment
34+
var (
35+
testEnv *helpers.TestEnvironment
36+
ctx = ctrl.SetupSignalHandler()
37+
)
4338

44-
func TestAPIs(t *testing.T) {
45-
RegisterFailHandler(Fail)
46-
junitReporter := reporters.NewJUnitReporter("junit-controller.xml")
47-
RunSpecsWithDefaultAndCustomReporters(t, "Controller Suite", []Reporter{junitReporter})
39+
func TestMain(m *testing.M) {
40+
setup()
41+
defer teardown()
42+
m.Run()
4843
}
4944

50-
var _ = BeforeSuite(func(done Done) {
51-
By("bootstrapping test environment")
52-
testEnv = &envtest.Environment{
53-
CRDDirectoryPaths: []string{
54-
filepath.Join("..", "config", "crd", "bases"),
55-
},
56-
}
57-
45+
// Setting up the test environment.
46+
func setup() {
47+
utilruntime.Must(infrav1beta1.AddToScheme(scheme.Scheme))
48+
utilruntime.Must(capiv1beta1.AddToScheme(scheme.Scheme))
49+
testEnvConfig := helpers.NewTestEnvironmentConfiguration([]string{
50+
path.Join("config", "crd", "bases"),
51+
},
52+
).WithWebhookConfiguration("unmanaged", path.Join("config", "webhook", "manifests.yaml"))
5853
var err error
59-
cfg, err = testEnv.Start()
60-
Expect(err).ToNot(HaveOccurred())
61-
Expect(cfg).ToNot(BeNil())
62-
63-
Expect(capiv1beta1.AddToScheme(scheme.Scheme)).To(Succeed())
64-
Expect(infrav1beta1.AddToScheme(scheme.Scheme)).To(Succeed())
65-
66-
// +kubebuilder:scaffold:scheme
67-
68-
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
69-
Expect(err).ToNot(HaveOccurred())
70-
Expect(k8sClient).ToNot(BeNil())
71-
72-
close(done)
73-
}, 60)
54+
testEnv, err = testEnvConfig.Build()
55+
if err != nil {
56+
panic(err)
57+
}
58+
if err := (&infrav1beta1.IBMPowerVSCluster{}).SetupWebhookWithManager(testEnv); err != nil {
59+
panic(fmt.Sprintf("Unable to setup IBMPowerVSCluster webhook: %v", err))
60+
}
61+
if err := (&infrav1beta1.IBMPowerVSMachine{}).SetupWebhookWithManager(testEnv); err != nil {
62+
panic(fmt.Sprintf("Unable to setup IBMPowerVSMachine webhook: %v", err))
63+
}
64+
if err := (&infrav1beta1.IBMPowerVSMachineTemplate{}).SetupWebhookWithManager(testEnv); err != nil {
65+
panic(fmt.Sprintf("Unable to setup IBMPowerVSMachineTemplate webhook: %v", err))
66+
}
67+
if err := (&infrav1beta1.IBMPowerVSImage{}).SetupWebhookWithManager(testEnv); err != nil {
68+
panic(fmt.Sprintf("Unable to setup IBMPowerVSImage webhook: %v", err))
69+
}
70+
if err := (&infrav1beta1.IBMVPCCluster{}).SetupWebhookWithManager(testEnv); err != nil {
71+
panic(fmt.Sprintf("Unable to setup IBMVPCCluster webhook: %v", err))
72+
}
73+
if err := (&infrav1beta1.IBMVPCMachine{}).SetupWebhookWithManager(testEnv); err != nil {
74+
panic(fmt.Sprintf("Unable to setup IBMVPCMachine webhook: %v", err))
75+
}
76+
if err := (&infrav1beta1.IBMVPCMachineTemplate{}).SetupWebhookWithManager(testEnv); err != nil {
77+
panic(fmt.Sprintf("Unable to setup IBMVPCMachineTemplate webhook: %v", err))
78+
}
79+
go func() {
80+
fmt.Println("Starting the manager")
81+
if err := testEnv.StartManager(ctx); err != nil {
82+
panic(fmt.Sprintf("Failed to start the envtest manager: %v", err))
83+
}
84+
}()
85+
testEnv.WaitForWebhooks()
86+
}
7487

75-
var _ = AfterSuite(func() {
76-
By("tearing down the test environment")
77-
err := testEnv.Stop()
78-
Expect(err).ToNot(HaveOccurred())
79-
})
88+
func teardown() {
89+
if err := testEnv.Stop(); err != nil {
90+
panic(fmt.Sprintf("Failed to stop envtest: %v", err))
91+
}
92+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/stretchr/testify v1.7.2
1919
golang.org/x/text v0.3.7
2020
k8s.io/api v0.23.5
21+
k8s.io/apiextensions-apiserver v0.23.5
2122
k8s.io/apimachinery v0.23.5
2223
k8s.io/client-go v0.23.5
2324
k8s.io/klog/v2 v2.30.0
@@ -134,7 +135,6 @@ require (
134135
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
135136
gopkg.in/yaml.v2 v2.4.0 // indirect
136137
gopkg.in/yaml.v3 v3.0.1 // indirect
137-
k8s.io/apiextensions-apiserver v0.23.5 // indirect
138138
k8s.io/apiserver v0.23.5 // indirect
139139
k8s.io/cluster-bootstrap v0.23.0 // indirect
140140
k8s.io/component-base v0.23.5 // indirect

0 commit comments

Comments
 (0)