我有一个生成器,可以在 Go 中生成代码,例如:
生成后,我需要测试我的生成器是否运行良好。对于每个生成的文件,我都有一个测试副本:
现在的问题是,有数百个这样的测试,并且考虑到项目的性质,其中一些有时会被破坏 - 即潜在的“foo.go”甚至可能由于语法错误或类似的原因而无法编译。
我想做的是:
为了让事情变得更复杂,理想情况下我希望将生成文件(foo.go)与测试文件(foo_test.go)分开 - 都在单独的目录和单独的 Go 包中,类似这样:
将它们保存在单独的目录中可以轻松清理和分离版本控制问题。将它们保存在单独的 Go 包中可以测试我需要生成的所有接口确实是公共的,并且可以保证测试永远不会触及私有字段。
算法:
go.mod
+ go.sum
以及必要的依赖项和模块声明package my_tests
go test -v foo.go foo_test.go bar.go bar_test.go
go test -v foo.go foo_test.go bar_test.go
→然后最终go test -v foo.go foo_test.go
,因为如果没有bar_test.go
,
bar.go
将无法生存.
这确实可行,但缺点是巨大的:我必须将所有内容放在一个目录中(因此 git 管理变得非常混乱)并且我必须将所有内容放在一个 Go 包中(这意味着使用私有字段进行测试时偶尔可能会出现错误)滑进去)。
算法:
两个独立的模块位于不同的目录中,每个模块都有自己的
go.mod
+ go.sum
。
首先,我尝试使用
generated
编译 go build foo.go bar.go
包和模块 → bar.go 已损坏 → go build foo.go
成功构建包
接下来,我转到
tests
包和模块。那个有 go.mod
包括替换指令:
replace my_generated => ../generated
在其中,我尝试做
go test -v foo_test.go
— 但是,唉,这似乎不起作用,因为 go test
将确保重建完整的包“my_ generated”,而这最终会失败,就像之前我那样我只是通过手动指定允许的文件列表才成功。
与之前相同,但不是从
go build
/ go test
调用中删除文件,而是硬禁用 go 编译器查找它们、删除或重命名它们。
可以工作,但它真的很难看,因为它修改了测试目录,所以我要么需要完整复制它并在单独的位置运行它,要么重命名 .go -> .disabled,然后在测试运行后将其重命名回来。
那么,问题是:我可以在这里采用更好的方法/算法吗?也许 go build 系统中有一些不明显的开关?
也许 go build 系统中有一些不明显的开关?
正如评论中提到的,构建约束可以提供删除文件的替代方法。
例如,如果
foo.go
和 foo_test.go
具有约束 //go:build !foo
,则使用 go test -tags foo
将排除这些文件(并且您可以指定多个标签 go test -tags foo,bar
)。
注意:这实际上只是回答您寻求其他选择的具体问题。我无法评论这是否真的是一个好的选择(你的问题集中在什么,并没有真正提到为什么)。