-
Notifications
You must be signed in to change notification settings - Fork 1.6k
🌱 (cli; alpha commands): Add unit tests for alpha commands [WiP] #4931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
Copyright 2023 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package alpha | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
// Figuring out ways to test run these tests similar to existing. | ||
// Currently unable to run without this on VSCode. Will remove once done | ||
func TestCommand(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "alpha") | ||
} | ||
|
||
var _ = Describe("NewScaffoldCommand", func() { | ||
|
||
When("NewScaffoldCommand", func() { | ||
It("Testing the NewScaffoldCommand", func() { | ||
cmd := NewScaffoldCommand() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The alpha update command internal code it might be nice if we could cover something There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, I am working on the update internal code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a tip: You can validate the code locally with:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you finish this one please remove WIP from the title so that we are aware of and we can review/get merged get done ;-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @cmallikarjunah, I'm currently working on alpha internal update package, are you working on the same or is it different?. I wanted to clarify so that we dont duplicate the work :-) https://github.com/kubernetes-sigs/kubebuilder/tree/master/pkg/cli/alpha/internal/update There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ya it's the same @mayuka-c. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, no worries, you can continue |
||
Expect(cmd).NotTo(BeNil()) | ||
Expect(cmd.Use).NotTo(Equal("")) | ||
Expect(cmd.Use).To(ContainSubstring("generate")) | ||
Expect(cmd.Short).NotTo(Equal("")) | ||
Expect(cmd.Short).To(ContainSubstring("Re-scaffold a Kubebuilder project from its PROJECT file")) | ||
Expect(cmd.Example).NotTo(Equal("")) | ||
Expect(cmd.Example).To(ContainSubstring("kubebuilder alpha generate")) | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,7 +75,7 @@ func (opts *Update) defineFromVersion(config store.Store) (string, error) { | |
|
||
func (opts *Update) defineToVersion() string { | ||
if len(opts.ToVersion) != 0 { | ||
if !strings.HasPrefix(opts.FromVersion, "v") { | ||
if !strings.HasPrefix(opts.ToVersion, "v") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please rebase with master? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure Camila, will do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @camilamacedo86 I have rebased. But the code in master still checks prefix for opts.FromVersion in function defineToVersion(). Can you re-check and confirm if this change is not needed? |
||
return "v" + opts.ToVersion | ||
} | ||
return opts.ToVersion | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
/* | ||
Copyright 2025 The Kubernetes Authors. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package update | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/h2non/gock" | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
"sigs.k8s.io/kubebuilder/v4/pkg/cli/alpha/internal/common" | ||
"sigs.k8s.io/kubebuilder/v4/pkg/config" | ||
"sigs.k8s.io/kubebuilder/v4/pkg/config/store/yaml" | ||
v3 "sigs.k8s.io/kubebuilder/v4/pkg/config/v3" | ||
) | ||
|
||
func TestCommand(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "update") | ||
} | ||
|
||
var _ = Describe("Prepare for internal update", func() { | ||
var ( | ||
tmpDir string | ||
workDir string | ||
projectFile string | ||
) | ||
|
||
BeforeEach(func() { | ||
tmpDir, _ = os.MkdirTemp("", "kubebuilder-prepare-test") | ||
workDir, _ = os.Getwd() | ||
os.Chdir(tmpDir) | ||
projectFile = filepath.Join(tmpDir, yaml.DefaultPath) | ||
|
||
config.Register(config.Version{Number: 3}, func() config.Config { | ||
return &v3.Cfg{Version: config.Version{Number: 3}, CliVersion: "1.0.0"} | ||
}) | ||
|
||
gock.New("https://api.github.com"). | ||
Get("/repos/kubernetes-sigs/kubebuilder/releases/latest"). | ||
Reply(200). | ||
JSON(map[string]string{ | ||
"tag_name": "v1.1.0", | ||
}) | ||
}) | ||
|
||
AfterEach(func() { | ||
os.Chdir(workDir) | ||
os.RemoveAll(tmpDir) | ||
defer gock.Off() | ||
}) | ||
|
||
Context("Prepare", func() { | ||
DescribeTable("should succeed for valid options", | ||
func(options *Update) { | ||
|
||
const version = `version: "3"` | ||
Expect(os.WriteFile(projectFile, []byte(version), 0o644)).To(Succeed()) | ||
|
||
result := options.Prepare() | ||
Expect(result).To(BeNil()) | ||
Expect(options.Prepare()).To(Succeed()) | ||
Expect(options.FromVersion).To(Equal("v1.0.0")) | ||
Expect(options.ToVersion).To(Equal("v1.1.0")) | ||
}, | ||
Entry("options", &Update{FromVersion: "v1.0.0", ToVersion: "v1.1.0", FromBranch: "test"}), | ||
Entry("options", &Update{FromVersion: "1.0.0", ToVersion: "1.1.0", FromBranch: "test"}), | ||
Entry("options", &Update{FromVersion: "v1.0.0", ToVersion: "v1.1.0"}), | ||
Entry("options", &Update{FromVersion: "1.0.0"}), | ||
Entry("options", &Update{ToVersion: "1.1.0"}), | ||
Entry("options", &Update{}), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we reduce the number of test cases here? Do we really need all of them to cover the intended scenarios?
We’re not actually validating SemVer parsing here, so duplicating every combination may be unnecessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. Will remove those. |
||
) | ||
|
||
DescribeTable("Should fail to prepare if project path is undetermined", | ||
func(options *Update) { | ||
result := options.Prepare() | ||
Expect(result).NotTo(BeNil()) | ||
Expect(result.Error()).Should(ContainSubstring("failed to determine project path")) | ||
}, | ||
Entry("options", &Update{FromVersion: "v1.0.0", ToVersion: "v1.1.0", FromBranch: "test"}), | ||
) | ||
|
||
DescribeTable("Should fail if PROJECT config could not be loaded", | ||
func(options *Update) { | ||
const version = "" | ||
Expect(os.WriteFile(projectFile, []byte(version), 0o644)).To(Succeed()) | ||
|
||
result := options.Prepare() | ||
Expect(result).NotTo(BeNil()) | ||
Expect(result.Error()).Should(ContainSubstring("failed to load PROJECT config")) | ||
}, | ||
Entry("options", &Update{FromVersion: "v1.0.0", ToVersion: "v1.1.0", FromBranch: "test"}), | ||
) | ||
|
||
DescribeTable("Should fail if FromVersion cannot be determined", | ||
func(options *Update) { | ||
|
||
config.Register(config.Version{Number: 3}, func() config.Config { | ||
return &v3.Cfg{Version: config.Version{Number: 3}} | ||
}) | ||
|
||
const version = `version: "3"` | ||
Expect(os.WriteFile(projectFile, []byte(version), 0o644)).To(Succeed()) | ||
|
||
// TODO: Update test. err is Nil as default branch in Prepare() is being hardcoded to "main". | ||
// Hence, the defineFromVersion condition will never fail. | ||
// result := options.Prepare() | ||
// Expect(result).NotTo(BeNil()) | ||
// Expect(result.Error()).Should(ContainSubstring("failed to determine the version")) | ||
Expect(options.FromVersion).To(BeEquivalentTo("")) | ||
}, | ||
Entry("options", &Update{}), | ||
) | ||
}) | ||
|
||
Context("DefineFromVersion", func() { | ||
|
||
DescribeTable("Should succeed when branch or CliVersion in Project config is present", | ||
func(options *Update) { | ||
|
||
const version = `version: "3"` | ||
Expect(os.WriteFile(projectFile, []byte(version), 0o644)).To(Succeed()) | ||
|
||
config, err := common.LoadProjectConfig(tmpDir) | ||
Expect(err).NotTo(HaveOccurred()) | ||
fromVersion, err := options.defineFromVersion(config) | ||
Expect(err).To(BeNil()) | ||
Expect(fromVersion).To(BeEquivalentTo("v1.0.0")) | ||
}, | ||
Entry("options", &Update{FromVersion: ""}), | ||
Entry("options", &Update{FromBranch: "test"}), | ||
Entry("options", &Update{FromVersion: "1.0.0", FromBranch: "test"}), | ||
) | ||
DescribeTable("Should fail when branch and CliVersion in Project config are absent", | ||
func(options *Update) { | ||
|
||
config.Register(config.Version{Number: 3}, func() config.Config { | ||
return &v3.Cfg{Version: config.Version{Number: 3}} | ||
}) | ||
|
||
const version = `version: "3"` | ||
Expect(os.WriteFile(projectFile, []byte(version), 0o644)).To(Succeed()) | ||
|
||
config, err := common.LoadProjectConfig(tmpDir) | ||
Expect(err).NotTo(HaveOccurred()) | ||
fromVersion, err := options.defineFromVersion(config) | ||
Expect(err).To(HaveOccurred()) | ||
Expect(err.Error()).To(ContainSubstring("no version specified in PROJECT file")) | ||
Expect(fromVersion).To(Equal("")) | ||
}, | ||
Entry("options", &Update{FromVersion: ""}), | ||
Entry("options", &Update{FromVersion: "v1.0.0"}), | ||
) | ||
}) | ||
|
||
Context("DefineToVersion", func() { | ||
|
||
DescribeTable("Should succeed.", | ||
func(options *Update) { | ||
toVersion := options.defineToVersion() | ||
Expect(toVersion).To(BeEquivalentTo("v1.1.0")) | ||
}, | ||
Entry("options", &Update{ToVersion: "1.1.0"}), | ||
Entry("options", &Update{ToVersion: "v1.1.0"}), | ||
Entry("options", &Update{}), | ||
) | ||
|
||
}) | ||
|
||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
Copyright 2023 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package alpha | ||
|
||
import ( | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("NewUpdateCommand", func() { | ||
|
||
When("NewUpdateCommand", func() { | ||
It("Testing the NewUpdateCommand", func() { | ||
cmd := NewUpdateCommand() | ||
Expect(cmd).NotTo(BeNil()) | ||
Expect(cmd.Use).NotTo(Equal("")) | ||
Expect(cmd.Use).To(ContainSubstring("update")) | ||
Expect(cmd.Short).NotTo(Equal("")) | ||
Expect(cmd.Short).To(ContainSubstring("Update a Kubebuilder project to a newer version")) | ||
}) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just more one nit: Could we aquash all commits we should have 1 commit per PR