在golang应用程序中组织测试并避免导入循环问题。

huangapple go评论86阅读模式
英文:

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

&lt;GOROOT&gt;/src/myapp/controllers/
&lt;GOROOT&gt;/src/myapp/controllers/account.go
...
&lt;GOROOT&gt;/src/myapp/models/
&lt;GOROOT&gt;/src/myapp/models/account.go
&lt;GOROOT&gt;/src/myapp/models/account_test.go
...
&lt;GOROOT&gt;/src/myapp/components/
&lt;GOROOT&gt;/src/myapp/components/comp1/
&lt;GOROOT&gt;/src/myapp/components/comp1/impl.go
&lt;GOROOT&gt;/src/myapp/components/comp1/impl_test.go
&lt;GOROOT&gt;/src/myapp/components/
...
&lt;GOROOT&gt;/src/myapp/testutil/
&lt;GOROOT&gt;/src/myapp/testutil/database.go
&lt;GOROOT&gt;/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.)

huangapple
  • 本文由 发表于 2013年11月19日 19:14:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/20069994.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定