Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Organizing tests in golang application and avoiding import cycles hell

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...

like image 369
Oleksandr Avatar asked Nov 19 '13 11:11

Oleksandr


1 Answers

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.)

like image 90
Volker Avatar answered Sep 29 '22 02:09

Volker