How to unit test command line flags in Go?

I would like the unit test to verify that a particular command line flag is in an enumeration.

Here is the code against which I would like to write tests:

var formatType string const ( text = "text" json = "json" hash = "hash" ) func init() { const ( defaultFormat = "text" formatUsage = "desired output format" ) flag.StringVar(&formatType, "format", defaultFormat, formatUsage) flag.StringVar(&formatType, "f", defaultFormat, formatUsage+" (shorthand)") } func main() { flag.Parse() } 

The required test would pass only if -format equals one of the constant values ​​indicated above. This value will be available in type. An example of a correct call might be: program -format text

What is the best way to test your desired behavior?

Note: I may have formulated it poorly, but the displayed code is not the unit test itself, but the code against which I want to write unit tests. This is a simple example from a tool that I am writing and wanted to ask if there is a good way to test valid input for a tool.

+9
source share
2 answers

Custom testing and flag handling can be achieved using flag.Var in flag .

Flag.Var "defines a flag with the specified name and usage string. The type and value of the flag is represented by the first argument of type Value, which usually contains a custom implementation of Value.

A flag.Value is any type that satisfies the Value interface, defined as:

 type Value interface { String() string Set(string) error } 

There is a good example flag source package in example_test.go

In your use case, you can use something like:

 package main import ( "errors" "flag" "fmt" ) type formatType string func (f *formatType) String() string { return fmt.Sprint(*f) } func (f *formatType) Set(value string) error { if len(*f) > 0 && *f != "text" { return errors.New("format flag already set") } if value != "text" && value != "json" && value != "hash" { return errors.New("Invalid Format Type") } *f = formatType(value) return nil } var typeFlag formatType func init() { typeFlag = "text" usage := `Format type. Must be "text", "json" or "hash". Defaults to "text".` flag.Var(&typeFlag, "format", usage) flag.Var(&typeFlag, "f", usage+" (shorthand)") } func main() { flag.Parse() fmt.Println("Format type is", typeFlag) } 

This is probably too large for such a simple example, but it can be very useful in defining more complex flag types (the linked example converts the list of intervals separated by commas into a slice of the user type based on time.Duration ).

EDIT: in response to how to run unit tests against flags, the most canonical example is flag_test.go in the source of the flag package . The section related to checking custom flag variables starts with Line 181 .

+9
source

I'm not sure if we agree with the term "unit test". What you want to achieve seems to me more like a fairly normal test in a program. You probably want to do something like this:

 func main() { flag.Parse() if formatType != text || formatType != json || formatType != hash { flag.Usage() return } // ... } 

Unfortunately, it is not easy to expand the Parser checkbox with your own value verifiers, so you should stick with this for now.

See Intermernet for a solution that defines the type of custom format and its validator.

0
source

Source: https://habr.com/ru/post/1489158/


All Articles