Skip to content

test(databackup): migrate controller tests to Ginkgo/Gomega#5713

Open
hxrshxz wants to merge 2 commits intofluid-cloudnative:masterfrom
hxrshxz:test/databackup-ginkgo-migration
Open

test(databackup): migrate controller tests to Ginkgo/Gomega#5713
hxrshxz wants to merge 2 commits intofluid-cloudnative:masterfrom
hxrshxz:test/databackup-ginkgo-migration

Conversation

@hxrshxz
Copy link
Copy Markdown
Contributor

@hxrshxz hxrshxz commented Mar 24, 2026

Ⅰ. Describe what this PR does

Migrate pkg/controllers/v1alpha1/databackup/ tests from stdlib testing to Ginkgo/Gomega and raise measured package coverage to 77.5%.

Ⅱ. Does this pull request fix one issue?

NONE

Ⅲ. List the added test cases (unit test/integration test) if any, please explain if no tests are needed.

  • Migrate pkg/controllers/v1alpha1/databackup/databackup_controller_test.go to Ginkgo/Gomega.
  • Migrate pkg/controllers/v1alpha1/databackup/status_handler_test.go to Ginkgo/Gomega.
  • Migrate pkg/controllers/v1alpha1/databackup/implement_test.go to Ginkgo/Gomega.
  • Add pkg/controllers/v1alpha1/databackup/suite_test.go for the package test suite.

Ⅳ. Describe how to verify it

  • make fmt
  • go test -coverprofile=/tmp/fluid-databackup.cover ./pkg/controllers/v1alpha1/databackup/... -count=1
  • go tool cover -func=/tmp/fluid-databackup.cover | grep total
  • rg 'testify' pkg/controllers/v1alpha1/databackup/*_test.go

Ⅴ. Special notes for reviews

N/A

- Add suite_test.go with package-level Ginkgo bootstrap (TestAPIs)
- Migrate status_handler_test.go from stdlib testing to Ginkgo/Gomega
- Add databackup_controller_test.go: NewDataBackupReconciler, Build, ControllerName
- Add implement_test.go: covers all dataBackupOperation methods including
  GetOperationObject, GetChartsDirectory, HasPrecedingOperation, Validate,
  UpdateStatusInfoForCompleted, GetTTL, GetStatusHandler, GetTargetDataset,
  UpdateOperationApiStatus, GetOperationType, GetPossibleTargetDatasetNamespacedNames,
  GetReleaseNameSpacedName, GetParallelTaskNumber, SetTargetDatasetStatusInProgress,
  RemoveTargetDatasetStatusInProgress

Coverage: 73.2% -> 77.5% (exceeds 75% gate)
Signed-off-by: Harsh <harshmastic@gmail.com>
Copilot AI review requested due to automatic review settings March 24, 2026 11:27
@fluid-e2e-bot
Copy link
Copy Markdown

fluid-e2e-bot bot commented Mar 24, 2026

Hi @hxrshxz. Thanks for your PR.

I'm waiting for a fluid-cloudnative member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the testing infrastructure for the databackup controller. By transitioning to Ginkgo and Gomega, the tests become more readable, expressive, and maintainable, aligning with modern Go testing practices. This change not only improves the quality of the existing tests but also expands coverage for critical components, enhancing the overall robustness of the data backup functionality.

Highlights

  • Test Framework Migration: Migrated existing unit tests for the databackup controller and status handler from Go's standard testing package to the Ginkgo/Gomega BDD testing framework.
  • New Test Coverage: Introduced new test cases for the dataBackupOperation struct, ensuring comprehensive coverage for its various methods and increasing measured package coverage to 77.5%.
  • Ginkgo Test Suite Setup: Added a dedicated suite_test.go file to properly initialize and configure the Ginkgo test suite for the databackup package.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates pkg/controllers/v1alpha1/databackup unit tests from testing/testify-style to the Ginkgo/Gomega BDD framework, aligning this controller package with the repo’s newer Ginkgo-based test suites and aiming to improve coverage.

Changes:

  • Added a Ginkgo suite entrypoint for the databackup controller test package.
  • Rewrote DataBackupReconciler tests using Ginkgo/Gomega.
  • Rewrote dataBackupOperation and OnceHandler tests using Ginkgo/Gomega, adding additional scenarios.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
pkg/controllers/v1alpha1/databackup/suite_test.go Adds Ginkgo suite runner and sets controller-runtime logger to a null logger for tests.
pkg/controllers/v1alpha1/databackup/databackup_controller_test.go Migrates reconciler unit tests to Ginkgo/Gomega.
pkg/controllers/v1alpha1/databackup/implement_test.go Adds Ginkgo/Gomega unit tests covering dataBackupOperation methods.
pkg/controllers/v1alpha1/databackup/status_handler_test.go Migrates OnceHandler status handler tests to Ginkgo/Gomega and expands scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +124 to +128
It("should return an OnceHandler", func() {
handler := op.GetStatusHandler()
Expect(handler).NotTo(BeNil())
_, ok := handler.(*OnceHandler)
Expect(ok).To(BeTrue())
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

GetStatusHandler() is only asserted to return an *OnceHandler, but the production implementation currently returns &OnceHandler{} without setting dataBackup. Since OnceHandler.GetOperationStatus() dereferences o.dataBackup, using the returned handler as-is will panic. Please either (a) change the production GetStatusHandler() to return a fully initialized handler, or (b) update this test to exercise handler.GetOperationStatus(...) (or at least assert the handler is configured) so this regression is caught.

Suggested change
It("should return an OnceHandler", func() {
handler := op.GetStatusHandler()
Expect(handler).NotTo(BeNil())
_, ok := handler.(*OnceHandler)
Expect(ok).To(BeTrue())
It("should return a properly configured OnceHandler", func() {
handler := op.GetStatusHandler()
Expect(handler).NotTo(BeNil())
onceHandler, ok := handler.(*OnceHandler)
Expect(ok).To(BeTrue())
// Ensure the OnceHandler is fully initialized so that GetOperationStatus will not panic.
Expect(onceHandler.dataBackup).NotTo(BeNil())

Copilot uses AI. Check for mistakes.
Comment on lines +152 to +156
It("should use conditions LastTransitionTime when conditions are set on succeeded pod", func() {
conditionTime := v1.Now()
mockPodWithConditions := corev1.Pod{
ObjectMeta: v1.ObjectMeta{
Name: "test-pod",
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This test case name says it verifies LastTransitionTime is used, but it only asserts the phase and that Conditions has length 1. Please assert something that actually depends on conditionTime (e.g., opStatus.Conditions[0].LastTransitionTime equals conditionTime, and/or Duration matches the expected value when CreationTimestamp is set) so the test will fail if the code falls back to time.Now() instead.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request successfully migrates the controller tests for the databackup package to use Ginkgo/Gomega, enhancing the test suite's structure and readability. The new tests cover various functionalities of the DataBackupReconciler and dataBackupOperation.

However, there is a logical error in one of the test expectations that needs to be addressed to ensure correctness.

Comment on lines +107 to +111
Expect(names).To(HaveLen(1))
Expect(names[0]).To(Equal(types.NamespacedName{
Namespace: "default",
Name: "test-backup",
}))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The GetPossibleTargetDatasetNamespacedNames method is expected to return the NamespacedName of the target dataset, which is specified in dataBackup.Spec.Dataset. However, this test currently asserts that the returned name is "test-backup", which is the name of the DataBackup object itself, not the dataset it targets. This is a logical error in the test expectation and should be corrected to "test-dataset" to accurately reflect the method's purpose.

            Expect(names[0]).To(Equal(types.NamespacedName{
                Namespace: "default",
                Name:      "test-dataset",
            }))

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.22%. Comparing base (8cda1f9) to head (d2428fe).
⚠️ Report is 16 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #5713   +/-   ##
=======================================
  Coverage   61.22%   61.22%           
=======================================
  Files         444      444           
  Lines       30557    30557           
=======================================
  Hits        18710    18710           
  Misses      10307    10307           
  Partials     1540     1540           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Strengthen the 'should use conditions LastTransitionTime' test to
actually verify the transition time value, not just the condition
count. Uses BeTemporally to handle metav1.Time second-precision
truncation.

Signed-off-by: Harsh <harshmastic@gmail.com>
@hxrshxz
Copy link
Copy Markdown
Contributor Author

hxrshxz commented Mar 24, 2026

/gemini review

@sonarqubecloud
Copy link
Copy Markdown

@hxrshxz
Copy link
Copy Markdown
Contributor Author

hxrshxz commented Mar 24, 2026

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request successfully migrates the tests for the databackup controller to use Ginkgo/Gomega, improving the test structure and coverage. The changes are generally well-implemented. I've included a couple of suggestions to refactor duplicated code in the new tests, which will enhance their readability and maintainability.

Comment on lines +56 to +81
It("should return a dataBackupOperation for a valid DataBackup object", func() {
s := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(s)
fakeClient := fake.NewFakeClientWithScheme(s)
log := ctrl.Log.WithName("test")
recorder := record.NewFakeRecorder(10)
r := NewDataBackupReconciler(fakeClient, log, s, recorder)

dataBackup := &datav1alpha1.DataBackup{}
op, err := r.Build(dataBackup)
Expect(err).NotTo(HaveOccurred())
Expect(op).NotTo(BeNil())
})

It("should return an error for a non-DataBackup object", func() {
s := runtime.NewScheme()
fakeClient := fake.NewFakeClientWithScheme(s)
log := ctrl.Log.WithName("test")
recorder := record.NewFakeRecorder(10)
r := NewDataBackupReconciler(fakeClient, log, s, recorder)

}
dataset := &datav1alpha1.Dataset{}
op, err := r.Build(dataset)
Expect(err).To(HaveOccurred())
Expect(op).To(BeNil())
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The setup for the reconciler is duplicated in both test cases within this Describe block. To improve readability and maintainability, you can extract the common setup into a BeforeEach block.

		var r *DataBackupReconciler
		BeforeEach(func() {
			s := runtime.NewScheme()
			_ = datav1alpha1.AddToScheme(s)
			fakeClient := fake.NewFakeClientWithScheme(s)
			log := ctrl.Log.WithName("test")
			recorder := record.NewFakeRecorder(10)
			r = NewDataBackupReconciler(fakeClient, log, s, recorder)
		})

		It("should return a dataBackupOperation for a valid DataBackup object", func() {
			dataBackup := &datav1alpha1.DataBackup{}
			op, err := r.Build(dataBackup)
			Expect(err).NotTo(HaveOccurred())
			Expect(op).NotTo(BeNil())
		})

		It("should return an error for a non-DataBackup object", func() {
			dataset := &datav1alpha1.Dataset{}
			op, err := r.Build(dataset)
			Expect(err).To(HaveOccurred())
			Expect(op).To(BeNil())
		})

Comment on lines +273 to +284
testScheme3 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme3)
_ = corev1.AddToScheme(testScheme3)
fakeClient3 := fake.NewFakeClientWithScheme(testScheme3, dataBackup, dataset)
op3 := &dataBackupOperation{
Client: fakeClient3,
Log: ctrl.Log.WithName("test"),
Recorder: record.NewFakeRecorder(10),
dataBackup: dataBackup,
}

got, err := op3.GetTargetDataset()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

This block contains redundant setup code. The testScheme is already created in the BeforeEach block and can be reused. Also, creating a new operation object (op3) for this test makes it verbose. A better approach is to update the client of the existing op object, which is reset for each test. This makes the test cleaner and easier to read.

A similar pattern of redundant setup is present in other tests like UpdateStatusInfoForCompleted and UpdateOperationApiStatus and could also be refactored.

Suggested change
testScheme3 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme3)
_ = corev1.AddToScheme(testScheme3)
fakeClient3 := fake.NewFakeClientWithScheme(testScheme3, dataBackup, dataset)
op3 := &dataBackupOperation{
Client: fakeClient3,
Log: ctrl.Log.WithName("test"),
Recorder: record.NewFakeRecorder(10),
dataBackup: dataBackup,
}
got, err := op3.GetTargetDataset()
op.Client = fake.NewFakeClientWithScheme(testScheme, dataBackup, dataset)
got, err := op.GetTargetDataset()

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request successfully migrates the controller tests for databackup to Ginkgo/Gomega, enhancing test readability and coverage. The changes are well-structured and the new tests cover more scenarios. I've included a few suggestions to further improve the test code by removing some redundancies, which will enhance maintainability.

Comment on lines +219 to +224
testScheme2 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme2)
_ = corev1.AddToScheme(testScheme2)
dataBackup2 := dataBackup.DeepCopy()
dataBackup2.Spec.BackupPath = "local:///tmp/backup"
fakeClient2 := fake.NewFakeClientWithScheme(testScheme2, dataBackup2, backupPod)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The testScheme is already initialized in the BeforeEach block and is accessible within this test case. Creating a new scheme testScheme2 is redundant. You can reuse testScheme when creating the fake client to make the test code cleaner and less repetitive.

Suggested change
testScheme2 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme2)
_ = corev1.AddToScheme(testScheme2)
dataBackup2 := dataBackup.DeepCopy()
dataBackup2.Spec.BackupPath = "local:///tmp/backup"
fakeClient2 := fake.NewFakeClientWithScheme(testScheme2, dataBackup2, backupPod)
dataBackup2 := dataBackup.DeepCopy()
dataBackup2.Spec.BackupPath = "local:///tmp/backup"
fakeClient2 := fake.NewFakeClientWithScheme(testScheme, dataBackup2, backupPod)

Comment on lines +242 to +245
testScheme4 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme4)
_ = corev1.AddToScheme(testScheme4)
fakeClient4 := fake.NewFakeClientWithScheme(testScheme4, dataBackup)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The testScheme is already initialized in the BeforeEach block. You can reuse it here instead of creating a new testScheme4.

Suggested change
testScheme4 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme4)
_ = corev1.AddToScheme(testScheme4)
fakeClient4 := fake.NewFakeClientWithScheme(testScheme4, dataBackup)
fakeClient4 := fake.NewFakeClientWithScheme(testScheme, dataBackup)

Comment on lines +273 to +276
testScheme3 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme3)
_ = corev1.AddToScheme(testScheme3)
fakeClient3 := fake.NewFakeClientWithScheme(testScheme3, dataBackup, dataset)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The testScheme is already initialized in the BeforeEach block. You can reuse it here instead of creating a new testScheme3.

Suggested change
testScheme3 := runtime.NewScheme()
_ = datav1alpha1.AddToScheme(testScheme3)
_ = corev1.AddToScheme(testScheme3)
fakeClient3 := fake.NewFakeClientWithScheme(testScheme3, dataBackup, dataset)
fakeClient3 := fake.NewFakeClientWithScheme(testScheme, dataBackup, dataset)

Copy link
Copy Markdown
Collaborator

@cheyang cheyang left a comment

Choose a reason for hiding this comment

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

/lgtm
/approve

Clean migration to Ginkgo/Gomega testing framework:

  • Well-structured tests using Describe/Context/It
  • Proper use of fake client for unit testing
  • Good coverage of both normal and error scenarios
  • Clear test naming (should...)
  • All CI checks pass

@fluid-e2e-bot
Copy link
Copy Markdown

fluid-e2e-bot bot commented Mar 27, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cheyang

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants