在Go的单元测试中自定义命令行标志

huangapple go评论72阅读模式
英文:

Custom command line flags in Go's unit tests

问题

有一个模块化的应用程序。有一堆使用一组应用程序模块的测试,每个测试需要不同的模块集。一些模块通过命令行进行调整,例如:

func init() {
    flag.StringVar(&this.customPath, "gamedir.custom", "", "Custom game resources directory")
}

但是我无法测试这个功能。如果我运行

go test -test.v ./... -gamedir.custom=c:/resources

运行时会返回以下错误信息:

flag provided but not defined: -gamedir.custom

并且测试失败。

我在测试命令行参数方面做错了什么?

英文:

Have a moduled application. Have a bunch of tests that use a set of application modules, each test requires different set. Some modules are tuned through the command-line, e.g:

func init() {
    flag.StringVar(&this.customPath, "gamedir.custom", "", "Custom game resources directory")
}

But I cannot test this functionality. If I run

go test -test.v ./... -gamedir.custom=c:/resources

the runtime answers with

flag provided but not defined: -gamedir.custom

and fails the test.

What am I doing wrong with testing command-line args?

答案1

得分: 19

我想我明白了,在我的情况下,标志出了什么问题。

使用以下命令:

go test -test.v ./... -gamedir.custom=c:/resources

编译器在工作区上运行一个或多个测试。在我特定的情况下,有多个测试,因为"./..."表示查找并为找到的每个_test.go文件创建测试可执行文件。测试可执行文件将应用所有附加参数除非其中一个或多个在其中被忽略
因此,使用参数的测试可执行文件通过测试,而其他所有测试失败。可以通过为每个test.go分别运行go test,并使用相应的参数集来覆盖这一点。

英文:

I think I got it what is wrong with flags in my case.
With the following command

go test -test.v ./... -gamedir.custom=c:/resources

the compiler runs one or several tests on a workspace. In my particular case there are several tests, because ./... means find and create test executable for every _test.go file found. The test executable applies all the additional params unless one or some of them is ignored within it.
Thus the test executables that do use param pass the test, all others fail. This may be overridden by running go test for each test.go separately, with appropriate set of params respectively.

答案2

得分: 13

你也会收到这个消息,如果你把标志声明放在一个测试中。不要这样做:

func TestThirdParty(t *testing.T) {
    foo := flag.String("foo", "", "the foobar bang")
    flag.Parse()
}

而是使用init函数:

var foo string
func init() {
    flag.StringVar(&foo, "foo", "", "the foo bar bang")
    flag.Parse()
}

func TestFoo() {
    // 根据需要使用foo...
}
英文:

You'll also get this message if you put your flag declarations inside of a test. Don't do this:

func TestThirdParty(t *testing.T) {
    foo := flag.String("foo", "", "the foobar bang")
    flag.Parse()
}

Instead use the init function:

var foo string
func init() {
    flag.StringVar(&foo, "foo", "", "the foo bar bang")
    flag.Parse()
}

func TestFoo() {
    // use foo as you see fit...
}

答案3

得分: 5

接受的答案,我发现并不完全清楚。为了传递一个参数给一个测试(而不出错),你必须首先使用标志来消耗该参数。对于上面的例子,其中gamedir.custom是一个传递的标志,你必须在你的测试文件中添加以下内容:

var gamedir *string = flag.String("gamedir.custom", "", "自定义游戏目录。")

或者将其添加到TestMain中。

英文:

The accepted answer, I found wasn't completely clear. In order to pass a parameter to a test (without an error) you must first consume that parameter using the flag. For the above example where gamedir.custom is a passed flag you must have this in your test file

var gamedir *string = flag.String("gamedir.custom", "", "Custom gamedir.")

Or add it to the TestMain

答案4

得分: 4

请注意,从Go 1.13开始,如果在init()函数中使用flag.Parse(),你将会得到以下错误:

flag provided but not defined: -test.timeout

要解决这个问题,你需要使用TestMain函数:

func TestMain(m *testing.M) {
    flag.Parse()
    os.Exit(m.Run())
}

TestFoo(t *testing.T) {}

希望对你有帮助!

英文:

Note that from Go 1.13, you'll get the following error if you use flag.Parse() in init()

> flag provided but not defined: -test.timeout

To fix this, you have to use TestMain

func TestMain(m *testing.M) {
	flag.Parse()
	os.Exit(m.Run())
}

TestFoo(t *testing.T) {}

huangapple
  • 本文由 发表于 2014年12月7日 21:14:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/27342973.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定