在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,或者通过提供更简单的数据使其运行得更快。
其次是使用约定,并调用TestUnitFoo
或TestIntegrationFoo
,然后使用-run
testing标志来表示要运行哪些testing。 所以你可以使用go test -run 'Unit'
进行unit testing, go test -run 'Integration'
集成testing。
第三个select是使用一个环境variables,并在os.Getenv
的testing设置中获得它。 那么你将使用简单的go test
unit testing和FOO_TEST_INTEGRATION=true go test
集成testing。
我个人更喜欢-short
解决scheme,因为它更简单,并且在标准库中使用,所以它似乎是分离/简化长时间运行testing的事实上的方法。 但是-run
和os.Getenv
解决scheme提供了更多的灵活性(还需要更多的谨慎,因为正则os.Getenv
涉及到-run
)。
为了详细说明我对@Ainar-G的出色答案的评论,在过去的一年中,我一直使用-short
和Integration
命名约定的组合来实现两全其美。
单元和集成testing和谐,在同一个文件中
以前的构build标志迫使我有多个文件( services_test.go
, services_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的惯例是:
- 在testing名称中使用
Integration
。 - 检查是否运行
-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标志定义在: