Search code examples
gogo-cobra

Passing Persistant flags for Cobra CLI for testing


I have a CLI application written in Cobra. The app contains a root command RootCmd which contains two PersistentFlags. One of the persistent flags is called threads which has a default value of 1 and shorthand -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.

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.

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. 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).

Is there a way to set flags other than SetArgs or a workaround?


Solution

  • I think I found the problem. Thanks to the example provided by 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:

    
    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.