[英]Passing Persistant flags for Cobra CLI for testing
I have a CLI application written in Cobra.我有一个用 Cobra 编写的 CLI 应用程序。 The app contains a root command
RootCmd
which contains two PersistentFlags
.该应用程序包含一个根命令
RootCmd
,其中包含两个PersistentFlags
。 One of the persistent flags is called threads
which has a default value of 1 and shorthand -h
.持久性标志之一称为
threads
,其默认值为 1 和简写-h
。
RootCmd.PersistentFlags().IntVarP(&threads, "threads", "t", 1, "Number of concurrent workers, using Stdin overrides this flag")
In the PersistentPreRun
I have a check if the value is set to less than 1 to print the error message threads can't be less than 1
and exit.在
PersistentPreRun
中,我检查该值是否设置为小于 1 以打印错误消息threads can't be less than 1
并退出。
The problem is I need to write some tests for the application and I can't find a way to set the flag.问题是我需要为应用程序编写一些测试,但我找不到设置标志的方法。 Currently, I test with
os/exec
, which is extremely annoying and doesn't provide code coverage.目前,我使用
os/exec
进行测试,这非常烦人并且不提供代码覆盖率。
I'm trying to do the following我正在尝试执行以下操作
func Test(t *testing.T) {
root := cmd.RootCmd
root.SetArgs([]string{"-t", "12"})
// or even: root.SetArgs([]string{"-t 12"})
root.Execute()
}
This outputs the message Error: unknown shorthand flag: 't' in -t 12
.这将输出消息
Error: unknown shorthand flag: 't' in -t 12
。 Omitting the flag entirely and trying to use any subcommand shows the error message that the value can't be less than one (mind you I set a default value).完全省略标志并尝试使用任何子命令会显示错误消息,指出该值不能小于 1(请注意,我设置了默认值)。
Is there a way to set flags other than SetArgs
or a workaround?有没有办法设置
SetArgs
以外的标志或解决方法?
I can't reproduce this problem.我无法重现这个问题。
I have a simple Cobra application I've created by running cobra-cli init
, and I've added a single subcommand, foo
.我有一个通过运行
cobra-cli init
创建的简单 Cobra 应用程序,并且添加了一个子命令foo
。 That gives me this layout:这给了我这个布局:
.
├── cmd
│ ├── foo.go
│ └── root.go
├── go.mod
├── go.sum
└── main.go
main.go
is minimal: main.go
是最小的:
package main
import "clitest/cmd"
func main() {
cmd.Execute()
}
In cmd/root.go
I add a single PersistentFlag
, --threads
(or -t
):在
cmd/root.go
,我添加了一个PersistentFlag
、 --threads
(或-t
):
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
)
var threads int
var rootCmd = &cobra.Command{
Use: "clitest",
Short: "A simple cli test",
RunE: runRoot,
}
func runRoot(cmd *cobra.Command, args []string) error {
fmt.Printf("This is the root command, threads=%d\n", threads)
return nil
}
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
rootCmd.PersistentFlags().IntVarP(&threads, "threads", "t", 1, "Number of threads")
}
In cmd/foo.go
I define a single subcommand:在
cmd/foo.go
,我定义了一个子命令:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var count int
var fooCmd = &cobra.Command{
Use: "foo",
Short: "The foo command",
RunE: runFoo,
}
func runFoo(cmd *cobra.Command, args []string) (err error) {
fmt.Printf("This is the foo command; count=%d\n", count)
return nil
}
func init() {
fooCmd.Flags().IntVarP(&count, "count", "c", 0, "Count of foo")
rootCmd.AddCommand(fooCmd)
}
With the above code in place, I can run:有了上面的代码,我可以运行:
$ ./clitest
This is the root command, threads=1
$ ./clitest -t 12
This is the root command, threads=12
$ ./clitest foo
This is the foo command; count=0, threads=1
$ ./clitest foo -t 12 -c 2
This is the foo command; count=2, threads=12
I can write a test for the root command like this:我可以像这样为 root 命令编写测试:
package cmd
import (
"testing"
)
func TestRootCmdWithArgs(t *testing.T) {
rootCmd.SetArgs([]string{"-t", "12"})
if err := rootCmd.Execute(); err != nil {
t.Errorf("failed to execute rootCmd")
}
if threads != 12 {
t.Errorf("expected 12, got %d", threads)
}
}
func TestRootCmdInvalidArgs(t *testing.T) {
rootCmd.SetArgs([]string{"--arg-that-does-not-exist"})
if err := rootCmd.Execute(); err == nil {
t.Errorf("command succeeded when it should have failed")
}
}
func TestFooCmdWithArgs(t *testing.T) {
rootCmd.SetArgs([]string{"foo", "-c", "2"})
if err := rootCmd.Execute(); err != nil {
t.Errorf("failed to execute rootCmd")
}
if count != 2 {
t.Errorf("execpted 2, got %d", count)
}
}
These tests succeed as expected:这些测试按预期成功:
$ go test ./...
? clitest [no test files]
ok clitest/cmd (cached)
You can find all the files referenced in this answer in this repository .您可以在此存储库中找到此答案中引用的所有文件。
I think I found the problem.我想我发现了问题。 Thanks to the example provided by Iarsks.
感谢 Iarsks 提供的示例。
My previous root had我以前的根有
func Execute() {
RootCmd.CompletionOptions.HiddenDefaultCmd = true
RootCmd.PersistentFlags().IntVarP(&threads, "threads", "t", 1, "Number of concurrent workers, using Stdin overrides this flag")
RootCmd.PersistentFlags().StringVarP(&delimiter, "delimiter", "d", ",", "Choose delimiter")
if err := RootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "csvutil encountered an error while executing")
os.Exit(1)
}
}
I split this function into:我将这个 function 拆分为:
func init() {
RootCmd.CompletionOptions.HiddenDefaultCmd = true
RootCmd.PersistentFlags().IntVarP(&threads, "threads", "t", 1, "Number of concurrent workers, using Stdin overrides this flag")
RootCmd.PersistentFlags().StringVarP(&delimiter, "delimiter", "d", ",", "Choose delimiter")
}
func Execute() {
if err := RootCmd.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "csvutil encountered an error while executing")
os.Exit(1)
}
}
And now it works fine.现在它工作正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.