英文:
Set particular environment variables during execution of a test suite
问题
我想在Go中运行一个与环境变量有关的单元测试函数。
在某个时候,我会这样写(不是故意的):
for test := range tests {
for k, v := range test.envVars {
os.Setenv(k, v)
}
有没有办法确保在测试执行期间,通过对上述os.Setenv()
调用设置的变量将是测试函数可用的唯一环境变量?
英文:
I want to run a unit test fxn in Go which has to do with env vars.
At some point I go (no pun intended)
for test := range tests {
for k, v := range test.envVars {
os.Setenv(k, v)
}
Is there a way to make sure that during the test execution, the variables set by the call to os.Setenv()
above will be the only env vars available to the test function?
答案1
得分: 4
你可以使用os.Environ
获取当前的环境变量,并使用os.Unsetenv
来取消设置。
假设在测试完成后你需要恢复这些变量,你可以使用subtest和(*testing.T).Cleanup
来为每个环境创建一个子测试(https://play.golang.org/p/A5HGZwWm-NS):
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// 注意:在这个子测试或其父测试中不要调用t.Parallel,
// 否则环境将会被破坏。
//
// (但是,t的子测试可以并行运行。)
prevEnv := os.Environ()
for _, entry := range prevEnv {
parts := strings.SplitN(entry, "=", 2)
os.Unsetenv(parts[0])
}
for k, v := range tc.envVars {
os.Setenv(k, v)
}
t.Cleanup(func() {
for k := range tc.envVars {
os.Unsetenv(k)
}
for _, entry := range prevEnv {
parts := strings.SplitN(entry, "=", 2)
os.Setenv(parts[0], parts[1])
}
})
…
})
}
另外请注意,Go 1.17 添加了(*testing.T).Setenv
方法,它可以自动清理修改的环境变量。然而,目前还没有相应的(*testing.T).Unsetenv
方法。
如果你想要能够并行运行测试,你可以使用os/exec
和-test.run
标志来将特定的子测试重新执行为主测试进程的子进程,每个子进程都有自己独立的环境。
英文:
You can use os.Environ
to obtain the current environment and os.Unsetenv
to unset it.
Presumably you would also need to restore those variables after the test completes, for which you could use a subtest per environment with (*testing.T).Cleanup
(https://play.golang.org/p/A5HGZwWm-NS):
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// NOTE: do NOT call t.Parallel in this subtest or its parent,
// or the environment WILL be corrupted.
//
// (However, *subtests of* t may be run in parallel.)
prevEnv := os.Environ()
for _, entry := range prevEnv {
parts := strings.SplitN(entry, "=", 2)
os.Unsetenv(parts[0])
}
for k, v := range tc.envVars {
os.Setenv(k, v)
}
t.Cleanup(func() {
for k := range tc.envVars {
os.Unsetenv(k)
}
for _, entry := range prevEnv {
parts := strings.SplitN(entry, "=", 2)
os.Setenv(parts[0], parts[1])
}
})
…
})
}
Also note that Go 1.17 adds the (*testing.T).Setenv
method, which cleans up the modification automatically. However, there is not yet a corresponding (*testing.T).Unsetenv
.
If you want to be able to run tests in parallel, you could instead use subtests with os/exec
and the -test.run
flag to re-exec the particular subtest as a subprocess of the main test process, with its own distinct environment.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论