英文:
Process command line arguments in go test
问题
在Go语言的测试中,有没有办法获取命令行参数?
当你调用go test
时,显然不会运行main
函数,所以有没有办法处理命令行参数呢?
一种方法是使用flags
包,并在每个测试或被测试的函数中检查命令行参数,但这并不理想,因为你需要在很多地方都这样做,而不像在运行应用程序时只需要在main
函数中处理。
有人可能认为这样做是错误的,违背了单元测试的纯粹性:
- 并不是所有的测试都是单元测试。
- 不依赖于"ENV"变量,通过命令行参数传递参数是非常实用的。
顺便说一下,我最后在一个_test
文件中放置了一个init()
函数,并在调用main
函数时设置了通过flags设置的变量。
英文:
Is there a way to get the command line arguments in go "tests",
When you call go test
obviously your main
is not run, so is there a way to process command line arguments,
One way would be to use the flags
packages and check for the command line arguments in each test or function being tested, but that is not ideal for that you need to do this in lots and lots of places, unlike the way you to it just in main
when you run the application.
One may think it is a wrong thing to do, and that it is against purity of unit-tests:
- not all tests are unit tests
- it is very functional not to rely on "ENV" variables and actually pass the stuff as arguments in command line,
For the record I ended up putting an init()
function in one of my _test
files, and set the variable that is set through flags when the main is called this way.
答案1
得分: 16
环境配置最好保存在环境变量中,根据我的经验。你可以像这样依赖全局变量:
var envSetting = os.Getenv("TEST_ENV")
或者,如果使用标志是必需的,你可以将初始化代码放在名为init()的函数中。
func init() {
flags.Parse()
myEnv = *envFlag
// ...
}
英文:
Environmental configs are best kept in environment variables, in my experience. You can rely on global variables like so:
var envSetting = os.Getenv("TEST_ENV")
Alternatively, if using flags is a requirement, you could place your initialization code inside a function called init().
func init() {
flags.Parse()
myEnv = *envFlag
// ...
}
答案2
得分: 14
你可以直接测试主函数并传递参数。
以下是一个简单的示例,展示了一个标志和一对位置参数。
注意:不要将其命名为'TestMain',因为在Go 1.8中,这对测试框架有特殊含义。
package main
import (
"os"
"testing"
)
func TestMainFunc(t *testing.T) {
os.Args = append(os.Args, "--addr=http://b.com:566/something.avsc")
os.Args = append(os.Args, "Get")
os.Args = append(os.Args, `./some/resource/fred`)
main()
// 在这里进行测试结果,并决定通过/失败。
}
英文:
You can directly test main function and pass arguments.
Simple example showing a flag, and a pair of positional arguments
Note: Do NOT call it 'TestMain' that has a special meaning to the testing framework as of Go 1.8.
package main
import (
"os"
"testing"
)
func TestMainFunc(t *testing.T) {
os.Args = append(os.Args, "--addr=http://b.com:566/something.avsc")
os.Args = append(os.Args, "Get")
os.Args = append(os.Args, `./some/resource/fred`)
main()
// Test results here, and decide pass/fail.
}
答案3
得分: 9
一种替代方法是将main()
函数作为一个存根,在参数被flag.Parse()
处理后,仅仅调用另一个函数,例如:
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help for flagname")
}
func main() {
flag.Parse()
submain(flag.Args())
}
func submain(args []string) {
...
}
然后在你的测试中,可以在调用submain(...)
之前设置标志变量并建立参数,模拟命令行中建立标志和参数的过程。这种方法可以最大程度地提高测试覆盖率,而无需实际使用命令行。例如,在main_test.go
中,你可以这样编写:
func TestSomething(t *testing.T) {
flagvar = 23
args := []string{"a", "b", "c"}
submain(args)
...
}
英文:
An alternative approach is to make main()
be a stub that merely calls into another function after arguments are processed by flag.Parse()
, for example:
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help for flagname")
}
func main() {
flag.Parse()
submain(flag.Args)
}
func submain(args []string) {
...
}
Then in your tests, flag variables can be set and arguments established before calling submain(...)
simulating the command line establishment of flags and arguments. This approach can be used to maximize test coverage without actually using a command line. For example, in main_test.go, you might write:
func TestSomething(t *testing.T) {
flagvar = 23
args := []string{"a", "b", "c"}
submain(args)
...
}
答案4
得分: 6
请注意,配置文件名是硬编码的。
英文:
os.Args[1] = "-conf=my.conf"
flag.Parse()
Notice that the config file name is hard-coded.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论