在Go中分离unit testing和集成testing

在GoLang(testify)中是否有一个确定的分离unit testing和集成testing的最佳实践? 我有混合的unit testing(不依赖于任何外部资源,因此运行速度非常快)和集成testing(这依赖于任何外部资源,从而运行速度较慢)。 所以,当我说go test时候,我想能够控制是否包含集成go test

最直接的技术似乎是在main中定义一个-integrate标志:

 var runIntegrationTests = flag.Bool("integration", false , "Run the integration tests (in addition to the unit tests)") 

然后在每个集成testing的顶部添加一个if语句:

 if !*runIntegrationTests { this.T().Skip("To run this test, use: go test -integration") } 

这是我能做的最好的吗? 我搜查了certificate文件,看是否有一个命名约定或者为我完成了这个,但没有find任何东西。 我错过了什么吗?

@Ainar-G提出了几种伟大的模式来分离testing。

SoundCloud的这一套Go实践build议使用构build标记( 在构build包的“构build约束”部分中进行描述 )来select要运行的testing:

编写一个integration_test.go,并给它一个集成的构build标签。 为服务地址和连接string等东西定义(全局)标志,并在testing中使用它们。

 // +build integration var fooAddr = flag.String(...) func TestToo(t *testing.T) { f, err := foo.Connect(*fooAddr) // ... } 

去testing需要构build标签就像去build设,所以你可以打电话go test -tags=integration 。 它还综合了一个调用flag.Parse的包main,所以任何声明和可见的flags都将被处理并且可以用于你的testing。

作为一个类似的选项,您也可以通过使用构build条件// +build !unit来默认运行集成testing,然后运行go test -tags=unit

我看到三种可能的解决scheme 首先是使用短模式进行unit testing。 所以你可以使用go test -short和unit testing,但是没有-short标志来运行你的集成testing。 标准库使用短模式来跳过长时间运行的testing,或者通过提供更简单的数据使其运行得更快。

其次是使用约定,并调用TestUnitFooTestIntegrationFoo ,然后使用-runtesting标志来表示要运行哪些testing。 所以你可以使用go test -run 'Unit'进行unit testing, go test -run 'Integration'集成testing。

第三个select是使用一个环境variables,并在os.Getenv的testing设置中获得它。 那么你将使用简单的go testunit testing和FOO_TEST_INTEGRATION=true go test集成testing。

我个人更喜欢-short解决scheme,因为它更简单,并且在标准库中使用,所以它似乎是分离/简化长时间运行testing的事实上的方法。 但是-runos.Getenv解决scheme提供了更多的灵活性(还需要更多的谨慎,因为正则os.Getenv涉及到-run )。

为了详细说明我对@Ainar-G的出色答案的评论,在过去的一年中,我一直使用-shortIntegration命名约定的组合来实现两全其美。

单元和集成testing和谐,在同一个文件中

以前的构build标志迫使我有多个文件( services_test.goservices_integration_test.go等)。

相反,在下面的例子中,前两个是unit testing,最后我有一个集成testing:

 package services import "testing" func TestServiceFunc(t *testing.T) { t.Parallel() ... } func TestInvalidServiceFunc3(t *testing.T) { t.Parallel() ... } func TestPostgresVersionIntegration(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } ... } 

注意最后一个testing的惯例是:

  1. 在testing名称中使用Integration
  2. 检查是否运行-short标志指令。

基本上,规范是这样写的:“正常地写所有的testing,如果是长期运行的testing,或者集成testing,按照这个命名约定,检查一下对你的同行来说很好。

只运行unit testing:

 go test -v -short 

这为您提供了一个很好的消息,如:

 === RUN TestPostgresVersionIntegration --- SKIP: TestPostgresVersionIntegration (0.00s) service_test.go:138: skipping integration test 

仅运行集成testing:

 go test -run Integration 

这只运行集成testing。 用于生产烟雾testing金丝雀。

显然,这种方法的缺点是,如果有人go test ,没有-short标志,它将默认运行所有的testing – unit testing和集成testing。

实际上,如果你的项目足够大以便进行单元和集成testing,那么你很可能使用了一个Makefile ,你可以在这里使用简单的指令来使用go test -short 。 或者,把它放在你的README.md文件中,然后称之为一天。

上面的SoundCloud文档中的示例具有不幸的属性,即“标记”被解释为构build标记,不会被传递给testing代码。 如果你想遵循这个方法,请使用不同的标志名称。 我花了一点才弄清楚,cmd / go / {build,testflag} .go定义和解释flags

去testing标志定义在:

Interesting Posts