Shermans's Notes
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

golang - Using and testing `flag`

    Setting up flags in init

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    package main  
      
    import (  
       "flag"  
       "fmt"   "testing")  
      
    var flagDebug bool  
    var flagHost  string  
      
    func init() {  
       flag.BoolVar(&flagDebug, "debug", false, "enable debug output")  
       flag.StringVar(&flagHost, "host", "example.com", "set the host to connect to")  
       flag.Parse()  
    }  
      
    func TestFlags(t *testing.T) {  
       fmt.Println(flagDebug)  
       fmt.Println(flagHost)    
    }  
      
    func TestFlagsAgain(t *testing.T) {  
       fmt.Println(flagDebug)  
       fmt.Println(flagHost)    
    }
    

    Causes the test to not run as it failed flag parsing

    1
    2
    3
    4
    5
    6
    
    flag provided but not defined: -test.v
    Usage of /private/var/folders/bk/k_kbqfsx0qgcdj7t4jn9g5dc0000gn/T/GoLand/___TestFlags_in_flags_example_test_go.test:
      -debug
        	enable debug output
      -host string
        	set the host to connect to (default "example.com")
    

    Setting up flags in function

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    package main  
      
    import (  
       "flag"  
       "fmt"   "os"   "testing")  
      
    var flagDebug bool  
    var flagHost  string  
      
    func parseFlags() {  
       flag.BoolVar(&flagDebug, "debug", false, "enable debug output")  
       flag.StringVar(&flagHost, "host", "example.com", "set the host to connect to")  
       flag.Parse()  
    }  
      
    func TestAll(t *testing.T) {  
       t.Run("test flags", BasicFlags)  
       t.Run("change args", ChangeArgs)  
    }  
      
    func BasicFlags(t *testing.T) {  
       parseFlags()  
       fmt.Println(flagDebug)  
       fmt.Println(flagHost)    
    }  
      
    func ChangeArgs(t *testing.T) {  
       os.Args = []string{"test", "--debug", "false", "--host", "google.com" }  
       parseFlags()  
       fmt.Println(flagDebug)  
       fmt.Println(flagHost)    
    }
    

    Causes a panic:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    === RUN   TestAll
    === RUN   TestAll/test_flags
    false
    example.com
    === RUN   TestAll/change_args
    /private/var/folders/bk/k_kbqfsx0qgcdj7t4jn9g5dc0000gn/T/GoLand/___TestAll_in_flags_example_test_go.test flag redefined: debug
    --- FAIL: TestAll (0.00s)
        --- PASS: TestAll/test_flags (0.00s)
        --- FAIL: TestAll/change_args (0.00s)
    panic: /private/var/folders/bk/k_kbqfsx0qgcdj7t4jn9g5dc0000gn/T/GoLand/___TestAll_in_flags_example_test_go.test flag redefined: debug [recovered]
    	panic: /private/var/folders/bk/k_kbqfsx0qgcdj7t4jn9g5dc0000gn/T/GoLand/___TestAll_in_flags_example_test_go.test flag redefined: debug
    
    goroutine 6 [running]:
    testing.tRunner.func1.2({0x102f28240, 0x1400005a5d0})
    	/usr/local/go/src/testing/testing.go:1209 +0x258
    testing.tRunner.func1(0x140001189c0)
    	/usr/local/go/src/testing/testing.go:1212 +0x284
    panic({0x102f28240, 0x1400005a5d0})
    	/usr/local/go/src/runtime/panic.go:1038 +0x21c
    flag.(*FlagSet).Var(0x14000070120, {0x102f48100, 0x103027c80}, {0x102ef27b6, 0x5}, {0x102ef5485, 0x13})
    	/usr/local/go/src/flag/flag.go:879 +0x2d8
    flag.BoolVar(...)
    	/usr/local/go/src/flag/flag.go:638
    command-line-arguments.parseFlags()
    	/Users/shermanrose/Library/Application Support/JetBrains/GoLand2022.1/scratches/flags_example_test.go:13 +0x74
    command-line-arguments.ChangeArgs(0x140001189c0)
    	/Users/shermanrose/Library/Application Support/JetBrains/GoLand2022.1/scratches/flags_example_test.go:31 +0xdc
    testing.tRunner(0x140001189c0, 0x102f45550)
    	/usr/local/go/src/testing/testing.go:1259 +0xfc
    created by testing.(*T).Run
    	/usr/local/go/src/testing/testing.go:1306 +0x328
    

    Using a custom Flag Set

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    
    package main  
      
    import (  
       "flag"  
       "testing")  
      
    func TestAll(t *testing.T) {  
         
       tests  := map[string]struct{  
          args []string  
          wantsDebug bool  
          wantsHost string  
       }{  
          "args set 1" : {  
             args: []string{"prog", "--debug", "--host", "google.com"},    
             wantsDebug: true,  
             wantsHost: "google.com",  
           },  
          "args set 2" : {  
             args: []string{"prog", "--host", "github.com"},  
             wantsDebug: false,  
             wantsHost: "github.com",  
          },  
       }  
         
       for name, data :=  range tests {  
          t.Run(name, func(t *testing.T) {  
             var flagDebug bool  
             var flagHost string  
          flags := flag.NewFlagSet(data.args[0], flag.ContinueOnError)  
             flags.BoolVar(&flagDebug, "debug", false, "enable debug logging")  
             flags.StringVar(&flagHost, "host", "example.com", "set the host to connect to")  
               
             err := flags.Parse(data.args[1:])  
             if err != nil {  
                t.Fatalf("failed to parse args: %s", err.Error())    
             }  
               
             if flagDebug != data.wantsDebug {  
                t.Fatalf("didn't get expected debug value")  
             }  
      
             if flagHost != data.wantsHost{  
                t.Fatalf("didn't get expected host value")  
             }  
            
          })  
       }  
         
    }
    

    This test runs without errors