This is an automated archive.

The original was posted on /r/golang by /u/GlamorousBunchberry on 2023-09-03 18:48:03+00:00.


I thought I’d ask for some feedback here, because it feels like I’m straying far from “normal” go testing.

I’m building a cobra/viper app that does a lot of interaction with a database. For testing purposes, I want to stand up a MySQL database in a Docker container, create a schema, and then use it for all my tests, which live in various packages.

Setting up the container is easy, using testcontainers/mysql. But it takes a while, so I’d hate to be running the same container over and over again.

What I landed on was to make a suite_test.go at the top level of my project, which uses testify/suite. It creates the container in its SetupSuite() func, and shuts it down in its TearDownSuite() func.

In order to make those the absolute first and last things called, I’m importing all my other testify/suite classes explicitly in suite_test.go, and invoking them there, like this:

// Include test cases from different packages by calling their respective methods

func (mySuite \*AllTestsSuite) TestMySQL() {
    tester := &mysql.MySQLTestSuite{
        Suite:  mySuite.Suite,
        DBConn: mySuite,
    }
    suite.Run(mySuite.T(), tester)
}

DBConn is an interface I define here and again in the file that defines MySQLTestSuite, so I can pass the parent suite in as a source of shared data, like the host, port, and data source name of the MySQL database.

The thing that makes me question, though, is the fact that you can’t just import test code from another package. Which means I can’t put my other tests in normal *_test.go files; instead I’m creating a child package called “tests” for each package. That way suite_test.go can import “internal/database/mysql/tests” with the alias “mysql,” and then instantiate a mysql.MySQLTestSuite as you see above.

Since the code under …/mysql/tests isn’t normal test code, it doesn’t have any funcs with the with the signature “func TestFoo(t *testing.T)” – only suite_test.go does. There I have one testify test per sub-suite, which instantites the suite and then runs it, as you see above.

Is all this crazy? Is there a simpler way?

Thanks in advance!