Skip to content

Commit 2b8b6f2

Browse files
committed
add testify, tidy up
1 parent 0945459 commit 2b8b6f2

3 files changed

Lines changed: 37 additions & 63 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ fmt:
1919
go fmt ./...
2020

2121
test:
22-
KUBEBUILDER_ASSETS=$$(setup-envtest use -p path) go test -count=1 ./...
22+
KUBEBUILDER_ASSETS=$$(setup-envtest use -p path) go test ./...

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ require (
4040
github.com/prometheus/common v0.66.1 // indirect
4141
github.com/prometheus/procfs v0.16.1 // indirect
4242
github.com/spf13/pflag v1.0.9 // indirect
43+
github.com/stretchr/testify v1.11.1 // indirect
4344
github.com/x448/float16 v0.8.4 // indirect
4445
go.yaml.in/yaml/v2 v2.4.3 // indirect
4546
go.yaml.in/yaml/v3 v3.0.4 // indirect

internal/controller/controller_integration_test.go

Lines changed: 35 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import (
99

1010
"github.com/github/deployment-tracker/internal/metadata"
1111
"github.com/github/deployment-tracker/pkg/deploymentrecord"
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
1214
appsv1 "k8s.io/api/apps/v1"
1315
corev1 "k8s.io/api/core/v1"
1416
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1517
"k8s.io/client-go/kubernetes"
1618
k8smetadata "k8s.io/client-go/metadata"
19+
"k8s.io/client-go/tools/cache"
1720
"sigs.k8s.io/controller-runtime/pkg/envtest"
1821
)
1922

@@ -30,14 +33,14 @@ func (m *mockRecordPoster) PostOne(_ context.Context, record *deploymentrecord.D
3033
return m.err
3134
}
3235

33-
// Helper that allows tests to read captured records safely
36+
// Helper that allows tests to read captured records safely.
3437
func (m *mockRecordPoster) getRecords() []*deploymentrecord.DeploymentRecord {
3538
m.mu.Lock()
3639
defer m.mu.Unlock()
3740
return slices.Clone(m.records)
3841
}
3942

40-
func setup(t *testing.T, namespace string) (*envtest.Environment, context.CancelFunc, *kubernetes.Clientset, *mockRecordPoster) {
43+
func setup(t *testing.T, namespace string) (*kubernetes.Clientset, *mockRecordPoster) {
4144
t.Helper()
4245
testEnv := &envtest.Environment{}
4346

@@ -52,6 +55,10 @@ func setup(t *testing.T, namespace string) (*envtest.Environment, context.Cancel
5255
}
5356

5457
ctx, cancel := context.WithCancel(context.Background())
58+
t.Cleanup(func() {
59+
cancel()
60+
_ = testEnv.Stop()
61+
})
5562

5663
ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
5764
_, err = clientset.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
@@ -90,10 +97,14 @@ func setup(t *testing.T, namespace string) (*envtest.Environment, context.Cancel
9097
mockDeploymentrecord := &mockRecordPoster{}
9198
ctrl.apiClient = mockDeploymentrecord
9299

93-
go ctrl.Run(ctx, 1)
94-
time.Sleep(1 * time.Second)
100+
go func() {
101+
_ = ctrl.Run(ctx, 1)
102+
}()
103+
if !cache.WaitForCacheSync(ctx.Done(), ctrl.podInformer.HasSynced) {
104+
t.Fatal("timed out waiting for informer cache to sync")
105+
}
95106

96-
return testEnv, cancel, clientset, mockDeploymentrecord
107+
return clientset, mockDeploymentrecord
97108
}
98109

99110
func makeDeployment(t *testing.T, clientset *kubernetes.Clientset, owners []metav1.OwnerReference, namespace, name string) *appsv1.Deployment {
@@ -207,52 +218,12 @@ func deletePod(t *testing.T, clientset *kubernetes.Clientset, namespace, name st
207218
}
208219
}
209220

210-
// pollForRecords polls until the mock has at least minCount records, then returns them.
211-
func pollForRecords(t *testing.T, mock *mockRecordPoster, minCount int, timeout time.Duration) []*deploymentrecord.DeploymentRecord {
212-
t.Helper()
213-
deadline := time.After(timeout)
214-
for {
215-
records := mock.getRecords()
216-
if len(records) >= minCount {
217-
return records
218-
}
219-
select {
220-
case <-deadline:
221-
t.Fatalf("timed out waiting for at least %d records, got %d", minCount, len(records))
222-
case <-time.After(100 * time.Millisecond):
223-
}
224-
}
225-
}
226-
227-
// assertNoNewRecords polls for the given duration and fails if the record count deviates from expectedCount.
228-
func assertNoNewRecords(t *testing.T, mock *mockRecordPoster, expectedCount int, timeout time.Duration) {
229-
t.Helper()
230-
deadline := time.After(timeout)
231-
for {
232-
select {
233-
case <-deadline:
234-
if got := len(mock.getRecords()); got != expectedCount {
235-
t.Fatalf("expected %d records, got %d", expectedCount, got)
236-
}
237-
return
238-
case <-time.After(100 * time.Millisecond):
239-
if got := len(mock.getRecords()); got != expectedCount {
240-
t.Fatalf("expected %d records, got %d", expectedCount, got)
241-
}
242-
}
243-
}
244-
}
245-
246221
func TestControllerIntegration_KubernetesDeployment(t *testing.T) {
247222
if testing.Short() {
248223
t.Skip("skipping integration test in short mode")
249224
}
250225
namespace := "test-namespace"
251-
testEnv, cancel, clientset, mock := setup(t, namespace)
252-
defer func(testEnv *envtest.Environment, cancelFunc context.CancelFunc) {
253-
_ = testEnv.Stop()
254-
cancel()
255-
}(testEnv, cancel)
226+
clientset, mock := setup(t, namespace)
256227

257228
// Create deployment, replicaset, and pod; expect 1 record
258229
deployment := makeDeployment(t, clientset, []metav1.OwnerReference{}, namespace, "test-deployment")
@@ -269,13 +240,12 @@ func TestControllerIntegration_KubernetesDeployment(t *testing.T) {
269240
UID: replicaSet.UID,
270241
}}, namespace, "test-deployment-123456-1")
271242

272-
records := pollForRecords(t, mock, 1, 5*time.Second)
273-
if len(records) != 1 {
274-
t.Fatalf("expected 1 record, got %d", len(records))
275-
}
276-
if records[0].Status != deploymentrecord.StatusDeployed {
277-
t.Errorf("expected %s, got %s", deploymentrecord.StatusDeployed, records[0].Status)
278-
}
243+
require.Eventually(t, func() bool {
244+
return len(mock.getRecords()) >= 1
245+
}, 5*time.Second, 100*time.Millisecond)
246+
records := mock.getRecords()
247+
require.Len(t, records, 1)
248+
assert.Equal(t, deploymentrecord.StatusDeployed, records[0].Status)
279249

280250
// Create another pod in replicaset; the dedup cache should prevent a new record as there is only one worker
281251
// and no risk of multiple works processing before cache is set.
@@ -285,22 +255,25 @@ func TestControllerIntegration_KubernetesDeployment(t *testing.T) {
285255
Name: replicaSet.Name,
286256
UID: replicaSet.UID,
287257
}}, namespace, "test-deployment-123456-2")
288-
assertNoNewRecords(t, mock, 1, 5*time.Second)
258+
require.Never(t, func() bool {
259+
return len(mock.getRecords()) != 1
260+
}, 5*time.Second, 100*time.Millisecond)
289261

290262
// Delete second pod; still expect 1 record
291263
deletePod(t, clientset, namespace, "test-deployment-123456-2")
292-
assertNoNewRecords(t, mock, 1, 5*time.Second)
264+
require.Never(t, func() bool {
265+
return len(mock.getRecords()) != 1
266+
}, 5*time.Second, 100*time.Millisecond)
293267

294268
// Delete deployment, replicaset, and first pod; expect 2 records
295269
deleteDeployment(t, clientset, namespace, "test-deployment")
296270
deleteReplicaSet(t, clientset, namespace, "test-deployment-123456")
297271
deletePod(t, clientset, namespace, "test-deployment-123456-1")
298272

299-
records = pollForRecords(t, mock, 2, 5*time.Second)
300-
if len(records) != 2 {
301-
t.Fatalf("expected 2 records after deletion, got %d", len(records))
302-
}
303-
if records[1].Status != deploymentrecord.StatusDecommissioned {
304-
t.Errorf("expected second record to be %s, got %s", deploymentrecord.StatusDecommissioned, records[1].Status)
305-
}
273+
require.Eventually(t, func() bool {
274+
return len(mock.getRecords()) >= 2
275+
}, 5*time.Second, 100*time.Millisecond)
276+
records = mock.getRecords()
277+
require.Len(t, records, 2)
278+
assert.Equal(t, deploymentrecord.StatusDecommissioned, records[1].Status)
306279
}

0 commit comments

Comments
 (0)