我怎么知道我在"去测试"中运行

Rob*_*yon 24 unit-testing go

当我运行"go test"时,我想使用不同的配置文件.如果我在测试环境或正常环境中运行,我如何知道我的代码?是否有某种环境变量需要检查?

Pow*_*man 32

测试包在加载时修改全局环境:它注册了许多命令行标志.因此,我们可以检查这些标志是否已注册:

func init() {
    if flag.Lookup("test.v") == nil {
        fmt.Println("normal run")
    } else {
        fmt.Println("run under go test")
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它在golang 1.13中不起作用 (5认同)
  • 请务必注意,如果您在任何非*_test.go文件中导入测试,则此方法将无效.它将始终承担测试运行.当我添加一些允许测试的实用程序函数时,我遇到了这个问题.T为失败而传递. (2认同)

Von*_*onC 13

我如何知道我的代码是在测试上下文还是正常上下文中运行?

Go 1.22(2023 年第 3 季度)或 Go 1.23(2024 年第 1 季度)可以提供此功能,考虑到提案“ # 5600 测试:添加func Testing() bool”已被接受,并且目前正在实施。
参见CL 475496

测试:添加Testing功能

测试功能报告该程序是否是由“ ”创建的测试go test

src/testing/testing.go

// testBinary is set by cmd/go to "1" if this is a binary built by "go test".
// The value is set to "1" by a -X option to cmd/link. We assume that
// because this is possible, the compiler will not optimize testBinary
// into a constant on the basis that it is an unexported package-scope
// variable that is never changed. If the compiler ever starts implementing
// such an optimization, we will need some technique to mark this variable
// as "changed by a cmd/link -X option".
var testBinary = "0"

// Testing reports whether the current code is being run in a test.
// This will report true in programs created by "go test",
// false in programs created by "go build".
func Testing() bool {
    return testBinary == "1"
}
Run Code Online (Sandbox Code Playgroud)

例子

package main
import (
    "fmt"
    "testing"
)
func main() {
    fmt.Println(testing.Testing())
}

func TestTesting(t *testing.T) {
    if !testing.Testing() {
        t.Errorf("testing.Testing() == %t, want %t", testing.Testing(), true)
    }
}
Run Code Online (Sandbox Code Playgroud)

用例示例

我可以通过以下方式testing.Testing()轻松保护非单元测试代码:

// file/that/should/not/be/used/from/testing.go

func prodEnvironmentData() *Environment {
   if testing.Testing() {
       log.Fatal("Using production data in unit tests")
   }
   ....
}
Run Code Online (Sandbox Code Playgroud)


sae*_*gnu 10

由于这种flag.Lookup("test.v")方法对我不起作用,我想分享我自己的解决方案:

strings.HasSuffix(os.Args[0], ".test")
Run Code Online (Sandbox Code Playgroud)

要么

strings.Contains(os.Args[0], "/_test/")
Run Code Online (Sandbox Code Playgroud)

两者似乎都有效.

  • `flag.Lookup("test.v")`方法用来工作,现在它没有(我使用的是1.8.1). (4认同)
  • `strings.HasSuffix(os.Args [0],".test")`对我来说更可靠.有一个开发机器`strings.Contains(os.Args [0],"/ _ test /")`失败了. (2认同)

Jer*_*all 9

代码示例会有所帮助.但是从你的问题来看,听起来你已经硬编码了一个配置文件的路径,当你可能想要传递它时.

更改您正在测试的函数以获取定义配置文件的参数,然后在测试代码中传递与您在非测试代码中使用的路径不同的路径.在测试与生产时,您的代码具有不同的路径是不好的做法.


Oli*_*din 7

flag.Lookup("test.v") == nil方法似乎有效,但我建议使用TestMain,它专门设计用于允许特定的测试设置和拆卸。如果您在要测试的包中包含此方法,它将在您的各个测试之前调用,因此您可以设置全局标志或在调用 m.Run() 之前执行任何您想要执行的特定于测试的配置,如下所示

func TestMain(m *testing.M) {
    // test context initialization here
    os.Exit(m.Run())
}
Run Code Online (Sandbox Code Playgroud)

PS:这实际上是@calvin-sugianto 建议的,除了 Gin 与此无关

  • 这似乎是最好的答案,因为它记录在 golang.org 上并将继续受到支持。在我看来,应该避免基于未记录标志的答案。 (2认同)

Jam*_*dge 6

一种可能性是使用构建约束.如果你运行go test:

go test -tags testing pkgname
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用该标记选择将包含在包的标准版本中的文件,以及哪些文件将用于测试.

如果您将标准配置放在自己的文件中,那么在下面添加一行代码将确保它不用于测试:

// +build !testing
Run Code Online (Sandbox Code Playgroud)

然后,您可以将测试配置包含在其中一个*_test.go文件中,或者包含要求testing设置标记的其他文件中.

  • 理想情况下,不应该有任何类型的魔术词来表明代码在单元测试上下文中运行。“go test”应该设置_something_,表明这是单元测试。 (3认同)
  • 不,不应该。你是对的,不应该有一个必要的魔法词来表明在单元测试上下文中运行。不是来自 go test 也不是来自你。你的测试应该有一个*不同*的函数来设置你的测试文件然后显式调用的测试环境 (2认同)
  • “不同的功能设置”的问题在于它依赖于工程师的最大努力。如果我的框架需要在我的框架用户测试期间更换模拟测试位,我希望作为框架设计者在我的控制下自动完成。请注意,这并不排除测试在测试期间对我的框架行为进行改进的能力。但它确实依赖于我在测试环境中运行时知道的能力。 (2认同)

Pra*_*ram 5

我是 golang 新手,flag.Lookup("test.v")对我不起作用,所以我找到了通过在 init() 中设置 ENV 变量来识别上下文是否正在测试或正常的方法。

如果您有测试文件,例如 abc.text.go,请在 init() 中将环境变量“GO_ENV”设置为测试。

func init() {
    os.Setenv("GO_ENV", "testing")
}
Run Code Online (Sandbox Code Playgroud)

当你想知道上下文时,请使用 os.Getenv("GO_ENV")
abc.go

if os.Getenv("GO_ENV") == "testing" {

} else {

}
Run Code Online (Sandbox Code Playgroud)