Skip to content

Commit 6d6e66e

Browse files
e2e tests: improve e2e tests and make test-e2e target
- Ensure that kind is installed and running before run the tests. Otherwise it will fail since we need to load the Manager(Operator) image - Add logic to skip the installation of CertManager and/or Prometheus via envvars. - Ensure that the promethues and certmanager are installed in the suite test instead of beafore each test - Ensure that the image is build and load in the suite instead instead for each test - Add more comments to clarify the purpose of the tests - Add TODO(user) to clarify that is expected action for the users to suplement and/or customize their e2e tests according to their needs
1 parent 05dc844 commit 6d6e66e

File tree

24 files changed

+872
-392
lines changed

24 files changed

+872
-392
lines changed

docs/book/src/cronjob-tutorial/testdata/project/Makefile

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,21 @@ vet: ## Run go vet against code.
6767
test: manifests generate fmt vet envtest ## Run tests.
6868
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
6969

70-
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
71-
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
72-
test-e2e:
70+
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
71+
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
72+
# Prometheus and CertManager are installed by default; skip with:
73+
# - PROMETHEUS_INSTALL_SKIP=true
74+
# - CERT_MANAGER_INSTALL_SKIP=true
75+
.PHONY: test-e2e
76+
test-e2e: ## Run the e2e tests. Expected an isolated environment using Kind.
77+
@command -v kind >/dev/null 2>&1 || { \
78+
echo "Kind is not installed. Please install Kind manually."; \
79+
exit 1; \
80+
}
81+
@kind get clusters | grep -q 'kind' || { \
82+
echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
83+
exit 1; \
84+
}
7385
go test ./test/e2e/ -v -ginkgo.v
7486

7587
.PHONY: lint

docs/book/src/cronjob-tutorial/testdata/project/test/e2e/e2e_suite_test.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,70 @@ package e2e
1818

1919
import (
2020
"fmt"
21+
"os"
22+
"os/exec"
2123
"testing"
2224

2325
. "github.com/onsi/ginkgo/v2"
2426
. "github.com/onsi/gomega"
27+
28+
"tutorial.kubebuilder.io/project/test/utils"
29+
)
30+
31+
var (
32+
// Environment Variables(Optional):
33+
// - PROMETHEUS_INSTALL_SKIP=true: Skips the installation of Prometheus Operator during the test suite setup.
34+
// - CERT_MANAGER_INSTALL_SKIP=true: Skips the installation of CertManager during the test suite setup.
35+
//
36+
// These environment variables are useful when Prometheus or CertManager is already installed in the environment,
37+
// allowing you to avoid unnecessary re-installation and potential conflicts. If set, the respective uninstall steps
38+
// in the teardown phase will also be skipped.
39+
skipPrometheusInstall = os.Getenv("PROMETHEUS_INSTALL_SKIP") == "true"
40+
skipCertManagerInstall = os.Getenv("CERT_MANAGER_INSTALL_SKIP") == "true"
41+
42+
// projectImage stores the name of the image used in the example
43+
projectImage = "example.com/project:v0.0.1"
2544
)
2645

27-
// Run e2e tests using the Ginkgo runner.
46+
// TestE2E serves as the entry point for running the suite of end-to-end (e2e) tests for the project.
47+
// These e2e tests are designed to run in an isolated environment, often spinning up a temporary
48+
// environment specifically for testing. This ensures that the tests do not interfere with other
49+
// environments and provide a reliable validation of the system's behavior as a whole.
2850
func TestE2E(t *testing.T) {
2951
RegisterFailHandler(Fail)
30-
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project suite\n")
52+
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project integration test suite\n")
3153
RunSpecs(t, "e2e suite")
3254
}
55+
56+
var _ = BeforeSuite(func() {
57+
By("building the manager(Operator) image")
58+
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectImage))
59+
_, err := utils.Run(cmd)
60+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to build the manager(Operator) image")
61+
62+
By("loading the manager(Operator) image on Kind")
63+
err = utils.LoadImageToKindClusterWithName(projectImage)
64+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to load the manager(Operator) image into Kind")
65+
66+
// Setup Prometheus and CertManager before the suite if not skipped
67+
if !skipPrometheusInstall {
68+
_, _ = fmt.Fprintf(GinkgoWriter, "Installing Prometheus Operator...\n")
69+
Expect(utils.InstallPrometheusOperator()).To(Succeed(), "Failed to install Prometheus Operator")
70+
}
71+
if !skipCertManagerInstall {
72+
_, _ = fmt.Fprintf(GinkgoWriter, "Installing CertManager...\n")
73+
Expect(utils.InstallCertManager()).To(Succeed(), "Failed to install CertManager")
74+
}
75+
})
76+
77+
var _ = AfterSuite(func() {
78+
// Teardown Prometheus and CertManager after the suite if not skipped
79+
if !skipPrometheusInstall {
80+
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling Prometheus Operator...\n")
81+
utils.UninstallPrometheusOperator()
82+
}
83+
if !skipCertManagerInstall {
84+
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling CertManager...\n")
85+
utils.UninstallCertManager()
86+
}
87+
})

docs/book/src/cronjob-tutorial/testdata/project/test/e2e/e2e_test.go

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -29,63 +29,53 @@ import (
2929

3030
const namespace = "project-system"
3131

32+
// Define a set of end-to-end (e2e) tests to validate the behavior of the controller.
3233
var _ = Describe("controller", Ordered, func() {
34+
// Before running the tests, set up the environment by creating the namespace,
35+
// installing CRDs, and deploying the controller.
3336
BeforeAll(func() {
34-
By("installing prometheus operator")
35-
Expect(utils.InstallPrometheusOperator()).To(Succeed())
36-
37-
By("installing the cert-manager")
38-
Expect(utils.InstallCertManager()).To(Succeed())
39-
4037
By("creating manager namespace")
4138
cmd := exec.Command("kubectl", "create", "ns", namespace)
42-
_, _ = utils.Run(cmd)
39+
_, err := utils.Run(cmd)
40+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to create namespace")
41+
42+
By("installing CRDs")
43+
cmd = exec.Command("make", "install")
44+
_, err = utils.Run(cmd)
45+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to install CRDs")
46+
47+
By("deploying the controller-manager")
48+
cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", projectImage))
49+
_, err = utils.Run(cmd)
50+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to deploy the controller-manager")
4351
})
4452

53+
// After all tests have been executed, clean up by undeploying the controller, uninstalling CRDs,
54+
// and deleting the namespace.
4555
AfterAll(func() {
46-
By("uninstalling the Prometheus manager bundle")
47-
utils.UninstallPrometheusOperator()
56+
By("undeploying the controller-manager")
57+
cmd := exec.Command("make", "undeploy")
58+
_, _ = utils.Run(cmd)
4859

49-
By("uninstalling the cert-manager bundle")
50-
utils.UninstallCertManager()
60+
By("uninstalling CRDs")
61+
cmd = exec.Command("make", "uninstall")
62+
_, _ = utils.Run(cmd)
5163

5264
By("removing manager namespace")
53-
cmd := exec.Command("kubectl", "delete", "ns", namespace)
54-
_, _ = utils.Run(cmd)
65+
cmd = exec.Command("kubectl", "delete", "ns", namespace)
66+
_, err := utils.Run(cmd)
67+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to delete namespace")
5568
})
5669

70+
// The Context block contains the actual tests that validate the operator's behavior.
5771
Context("Operator", func() {
5872
It("should run successfully", func() {
5973
var controllerPodName string
60-
var err error
61-
62-
// projectimage stores the name of the image used in the example
63-
var projectimage = "example.com/project:v0.0.1"
64-
65-
By("building the manager(Operator) image")
66-
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectimage))
67-
_, err = utils.Run(cmd)
68-
ExpectWithOffset(1, err).NotTo(HaveOccurred())
69-
70-
By("loading the the manager(Operator) image on Kind")
71-
err = utils.LoadImageToKindClusterWithName(projectimage)
72-
ExpectWithOffset(1, err).NotTo(HaveOccurred())
73-
74-
By("installing CRDs")
75-
cmd = exec.Command("make", "install")
76-
_, err = utils.Run(cmd)
77-
ExpectWithOffset(1, err).NotTo(HaveOccurred())
78-
79-
By("deploying the controller-manager")
80-
cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", projectimage))
81-
_, err = utils.Run(cmd)
82-
ExpectWithOffset(1, err).NotTo(HaveOccurred())
8374

8475
By("validating that the controller-manager pod is running as expected")
8576
verifyControllerUp := func() error {
86-
// Get pod name
87-
88-
cmd = exec.Command("kubectl", "get",
77+
// Get the name of the controller-manager pod
78+
cmd := exec.Command("kubectl", "get",
8979
"pods", "-l", "control-plane=controller-manager",
9080
"-o", "go-template={{ range .items }}"+
9181
"{{ if not .metadata.deletionTimestamp }}"+
@@ -95,28 +85,31 @@ var _ = Describe("controller", Ordered, func() {
9585
)
9686

9787
podOutput, err := utils.Run(cmd)
98-
ExpectWithOffset(2, err).NotTo(HaveOccurred())
88+
ExpectWithOffset(2, err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information")
9989
podNames := utils.GetNonEmptyLines(string(podOutput))
10090
if len(podNames) != 1 {
101-
return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames))
91+
return fmt.Errorf("expected 1 controller pod running, but got %d", len(podNames))
10292
}
10393
controllerPodName = podNames[0]
10494
ExpectWithOffset(2, controllerPodName).Should(ContainSubstring("controller-manager"))
10595

106-
// Validate pod status
96+
// Validate the pod's status
10797
cmd = exec.Command("kubectl", "get",
10898
"pods", controllerPodName, "-o", "jsonpath={.status.phase}",
10999
"-n", namespace,
110100
)
111101
status, err := utils.Run(cmd)
112-
ExpectWithOffset(2, err).NotTo(HaveOccurred())
102+
ExpectWithOffset(2, err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod status")
113103
if string(status) != "Running" {
114104
return fmt.Errorf("controller pod in %s status", status)
115105
}
116106
return nil
117107
}
108+
// Repeatedly check if the controller-manager pod is running until it succeeds or times out.
118109
EventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed())
119-
120110
})
111+
112+
// TODO(user): Customize the e2e test suite to include
113+
// additional scenarios specific to your project.
121114
})
122115
})

docs/book/src/getting-started/testdata/project/Makefile

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,21 @@ vet: ## Run go vet against code.
6363
test: manifests generate fmt vet envtest ## Run tests.
6464
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
6565

66-
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
67-
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
68-
test-e2e:
66+
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
67+
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
68+
# Prometheus and CertManager are installed by default; skip with:
69+
# - PROMETHEUS_INSTALL_SKIP=true
70+
# - CERT_MANAGER_INSTALL_SKIP=true
71+
.PHONY: test-e2e
72+
test-e2e: ## Run the e2e tests. Expected an isolated environment using Kind.
73+
@command -v kind >/dev/null 2>&1 || { \
74+
echo "Kind is not installed. Please install Kind manually."; \
75+
exit 1; \
76+
}
77+
@kind get clusters | grep -q 'kind' || { \
78+
echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
79+
exit 1; \
80+
}
6981
go test ./test/e2e/ -v -ginkgo.v
7082

7183
.PHONY: lint

docs/book/src/getting-started/testdata/project/test/e2e/e2e_suite_test.go

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,70 @@ package e2e
1818

1919
import (
2020
"fmt"
21+
"os"
22+
"os/exec"
2123
"testing"
2224

2325
. "github.com/onsi/ginkgo/v2"
2426
. "github.com/onsi/gomega"
27+
28+
"example.com/memcached/test/utils"
29+
)
30+
31+
var (
32+
// Environment Variables(Optional):
33+
// - PROMETHEUS_INSTALL_SKIP=true: Skips the installation of Prometheus Operator during the test suite setup.
34+
// - CERT_MANAGER_INSTALL_SKIP=true: Skips the installation of CertManager during the test suite setup.
35+
//
36+
// These environment variables are useful when Prometheus or CertManager is already installed in the environment,
37+
// allowing you to avoid unnecessary re-installation and potential conflicts. If set, the respective uninstall steps
38+
// in the teardown phase will also be skipped.
39+
skipPrometheusInstall = os.Getenv("PROMETHEUS_INSTALL_SKIP") == "true"
40+
skipCertManagerInstall = os.Getenv("CERT_MANAGER_INSTALL_SKIP") == "true"
41+
42+
// projectImage stores the name of the image used in the example
43+
projectImage = "example.com/project:v0.0.1"
2544
)
2645

27-
// Run e2e tests using the Ginkgo runner.
46+
// TestE2E serves as the entry point for running the suite of end-to-end (e2e) tests for the project.
47+
// These e2e tests are designed to run in an isolated environment, often spinning up a temporary
48+
// environment specifically for testing. This ensures that the tests do not interfere with other
49+
// environments and provide a reliable validation of the system's behavior as a whole.
2850
func TestE2E(t *testing.T) {
2951
RegisterFailHandler(Fail)
30-
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project suite\n")
52+
_, _ = fmt.Fprintf(GinkgoWriter, "Starting project integration test suite\n")
3153
RunSpecs(t, "e2e suite")
3254
}
55+
56+
var _ = BeforeSuite(func() {
57+
By("building the manager(Operator) image")
58+
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectImage))
59+
_, err := utils.Run(cmd)
60+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to build the manager(Operator) image")
61+
62+
By("loading the manager(Operator) image on Kind")
63+
err = utils.LoadImageToKindClusterWithName(projectImage)
64+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to load the manager(Operator) image into Kind")
65+
66+
// Setup Prometheus and CertManager before the suite if not skipped
67+
if !skipPrometheusInstall {
68+
_, _ = fmt.Fprintf(GinkgoWriter, "Installing Prometheus Operator...\n")
69+
Expect(utils.InstallPrometheusOperator()).To(Succeed(), "Failed to install Prometheus Operator")
70+
}
71+
if !skipCertManagerInstall {
72+
_, _ = fmt.Fprintf(GinkgoWriter, "Installing CertManager...\n")
73+
Expect(utils.InstallCertManager()).To(Succeed(), "Failed to install CertManager")
74+
}
75+
})
76+
77+
var _ = AfterSuite(func() {
78+
// Teardown Prometheus and CertManager after the suite if not skipped
79+
if !skipPrometheusInstall {
80+
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling Prometheus Operator...\n")
81+
utils.UninstallPrometheusOperator()
82+
}
83+
if !skipCertManagerInstall {
84+
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling CertManager...\n")
85+
utils.UninstallCertManager()
86+
}
87+
})

0 commit comments

Comments
 (0)