如何在Go中单元测试命令行标志?

时间:2013-07-01 20:17:31

标签: unit-testing go

我想要一个单元测试来验证特定命令行标志是否在枚举中。

以下是我想编写测试的代码:

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()
}

只有当-format等于上面给出的一个const值时,才会传递所需的测试。此值可在formatType中使用。一个正确的调用示例是:program -format text

测试所需行为的最佳方法是什么?

注意:也许我的措辞很差,但显示的代码不是单元测试本身,而是我想编写单元测试的代码。这是我正在撰写的工具中的一个简单示例,并且想要询问是否有一种测试工具有效输入的好方法。

2 个答案:

答案 0 :(得分:10)

使用flag.Var包中的flag功能可以实现标志的自定义测试和处理。

Flag.Var “定义具有指定名称和用法字符串的标志。标志的类型和值由第一个参数表示,类型为Value,它通常包含用户定义的Value实现。 “

flag.Value是满足Value接口的任何类型,定义为:

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

example_test.go

中的flag package source文件中有一个很好的示例

对于您的用例,您可以使用以下内容:

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

这对于这样一个简单的例子来说可能有些过分,但在定义更复杂的标志类型时可能非常有用(链接的示例将逗号分隔的间隔列表转换为基于time.Duration的自定义类型的片段)

编辑:在回答如何针对标志运行单元测试时,最典型的例子是flag_test.go in the flag package source。与测试自定义标志变量相关的部分从Line 181开始。

答案 1 :(得分:0)

我不确定我们是否同意“单元测试”一词。你想要实现的目标在我看来 更像是一个程序中非常正常的测试。你可能想做这样的事情:

func main() {
    flag.Parse()

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

    // ...
}

遗憾的是,用自己的值验证器扩展标记Parser是不容易的 所以你现在必须坚持这一点。

请参阅Intermernet以获取定义自定义格式类型及其验证器的解决方案。