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
. That gives me this layout:
.
├── cmd
│ ├── foo.go
│ └── root.go
├── go.mod
├── go.sum
└── main.go
main.go
is minimal:
package main
import "clitest/cmd"
func main() {
cmd.Execute()
}
In cmd/root.go
I add a single PersistentFlag
, --threads
(or -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:
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:
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.