英文:
Organizing tests in golang application and avoiding import cycles hell
问题
我目前遇到了一个关于应用程序结构和测试基础设施的架构问题。
以下是布局的简要概述:
<GOROOT>/src/myapp/controllers/
<GOROOT>/src/myapp/controllers/account.go
...
<GOROOT>/src/myapp/models/
<GOROOT>/src/myapp/models/account.go
<GOROOT>/src/myapp/models/account_test.go
...
<GOROOT>/src/myapp/components/
<GOROOT>/src/myapp/components/comp1/
<GOROOT>/src/myapp/components/comp1/impl.go
<GOROOT>/src/myapp/components/comp1/impl_test.go
<GOROOT>/src/myapp/components/
...
<GOROOT>/src/myapp/testutil/
<GOROOT>/src/myapp/testutil/database.go
<GOROOT>/src/myapp/testutil/models.go
...
问题1:
文件myapp/testutil/models.go
包含在models/*_test.go
测试中使用的一些实用函数。
这些实用函数实际上使用了myapp/models
包中的数据结构和函数。因此,我们存在一个循环导入:account_test.go
导入了testutil
包,而testutil
包又导入了models
包。
在这种情况下,唯一明确的解决方案是将testutil/models.go
保留在models
包中,放在同一个包中,例如test_utils.go
,但这种方法对我来说有点笨拙。在这种情况下,有什么更好的解决方法吗?
问题2:
testutil
包对comp1
(假设它是一个第三方服务的客户端)进行了一些初始化。当我们运行测试comp1/impl_test.go
时,会导入testutil
包,并且它会导入comp1
包,因为它负责组件的初始化。同样是循环导入的问题。将初始化移动到每个测试用例中的各个位置似乎是代码重复。仍在寻找一些优雅的解决方案...
英文:
I'm currently experiencing a problem of architecting the application structure and its test infrastructure.
Here's a brief overview of the layout
<GOROOT>/src/myapp/controllers/
<GOROOT>/src/myapp/controllers/account.go
...
<GOROOT>/src/myapp/models/
<GOROOT>/src/myapp/models/account.go
<GOROOT>/src/myapp/models/account_test.go
...
<GOROOT>/src/myapp/components/
<GOROOT>/src/myapp/components/comp1/
<GOROOT>/src/myapp/components/comp1/impl.go
<GOROOT>/src/myapp/components/comp1/impl_test.go
<GOROOT>/src/myapp/components/
...
<GOROOT>/src/myapp/testutil/
<GOROOT>/src/myapp/testutil/database.go
<GOROOT>/src/myapp/testutil/models.go
...
Problem 1
File myapp/testutil/models.go
contains some util functions used in the models/*_test.go
tests.
The util functions actually do use the package myapp/models
data structures and functions. Therefore we have an import cycle: account_test.go
imports testutil
package, which in its turn imports models
.
The only clear solution here is to keep testutil/models.go
right inside of models
packages at the same package something like test_utils.go
, which seems a bit clumsy to me. What would deb the best walkaround in such cases?
Problem 2
testutil
package has some initialization of the comp1
(let's say it's a client to a 3rd party service). When we run a test comp1/impl_test.go
the testutil
package is imported, and it imports comp1
package as it's responsible for initialisation of the component. Same cyclic import hell. Moving initialisation to a every individual place in the test cases seems like a duplication of code. Still looking for some elegant solutions here...
答案1
得分: 8
问题1
如果package testutils
只提供在package module
的测试期间使用的实用函数,那么将这些函数放入models/testutils_test.go
中:现在这些实用函数将在运行models/*_test.go
测试时包含进去。不再存在导入循环。
这是你的“唯一明确的解决方案”,我看不出其中有任何“笨拙”的地方。
问题2
导入循环:与上述相同。
初始化:你的comp1/impl_test.go
可以提供一个func init()
,因此不需要重复的代码。
(标准库是测试不同内容的好资源。在测试代码中进行代码重复在我看来不是七宗罪之一。)
英文:
Problem 1
If package testutils
just provide utility functions used during testing of package module
then just put those functions into models/testutils_test.go
: Now these utility function will be included when running the models/*_test.go
tests. No import cycle any longer.
This is your "only clear solution" and I cannot see anything "clumsy" with it.
Problem 2
Import cycle: Same as above.
Initialization: Your comp1/impl_test.go
can provide a func init()
so no need for duplicated code.
(The standard library is good source of how to test different stuff. IMHO code duplication in testing code is not one of the seven deadly sins.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论