Organizing tests in golang application and avoiding import cycles hell

architecture, go, testing, web

Solution

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

Problem

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

Original source