3

I'm setting up some integration testing, which I'm doing in a separate test package to my src code. This is done to prevent circular dependencies. Unit tests are not stored here, they are stored alongside the files they are testing.

My golang project hierarchy looks like:

cmd public ... testing/ main_test.go database_test.go

in main_test.go, I plan to initialise the connections to external dependencies, such as my test database.

package tests

type Database struct {
...
}
var DB Database

func TestMain(m *testing.M){
 SetUpDatabase()
 exitCode := m.Run()
 os.Exit(exitCode)
}

database_integration_test.go

func Test(t *testing.T) {

    tests := []struct {
        title string
        run   func(t *testing.T)
    }{
        {"should make query", testQuery},

    }
    for _, test := range tests {
        t.Run(test.title, func(t *testing.T) {
            test.run(t)
        })
    }
}

func testQuery(t *testing.T) {

    var r result.Result
    err := DB.database.DoQuery("").Decode(&r)

    if err != nil {
        t.Errorf(err.Error())
        t.Fatal()
    }
}

This setup works when I run it, however, I would like to add build tags to these files, or the type: // +build integration However, as soon as I use the build tag, the database_integration_test.go file cannot see the initalised Database type. How can I stop this? Also as a side note, should I change the name of main_test.go. I only called it that due to main being the standrd entry point.

testing495
  • 212
  • 2
  • 12

2 Answers2

5

Firstly, Regarding this:

Also as a side note, should I change the name of main_test.go. I only called it that due to main being the standard entry point.

I think it is confusing to name it as main_test.go as it might indicate that you are testing the main function in this file (according to golang convention)

Secondly, Regarding this:

However, as soon as I use the build tag, the database_integration_test.go file cannot see the initialised Database type. How can I stop this?

A Build Constraint or also known as Build Tag is used to include or exclude files in a package during a build process. With this, we can build different types of builds from the same source code.

So if you are not seeing the Database Type initialized then most probably the definition of the Database Type and the integration test are tagged with different build tags. Make sure they are present in the same build tags. Also, I think you can use more than one build tag to label a file. So you can try that as well.

For more details on the Build Tags check out the following article by Dave Cheney here

Sai Ravi Teja K
  • 569
  • 4
  • 11
  • 1
    As I understand it, these are meant to be integration tests. `main_test.go` would not live next to the standard `main` function. As such, I don't think there's much risk of people believing this being a unit test covering the `main` function. – Elias Van Ootegem Apr 12 '21 at 16:16
1

You could simply add a flag to your TestMain:

var isIntegration bool

func init() {
    flag.StringVar(&isIntegration, "mytest.integration", "Set flag to set up DB for integration tests")
}

func TestMain(t *testing.M) {
    SetUpDatabase(isIntegration)
    //etc...
}

Then just simply have the SetUpDatabase call different, unexported, functions based on whether or not the argument is true or false. That'd be a quick way to get the behaviour, without having to much about with custom build constraints. Especially considering you're running tests, not building the application as-such.

As far as renaming main_test.go is concerned: I don't see why you'd need to change it. It does what it says on the tin. When someone else wants to see how the tests are structured/run, or what possible flags have been added, it's a lot easier to just check the directory and look for a main_test.go file (along with init.go, that'd be first file I'd look for). Any other name like setup_integration_test.go, integration_setup_test.go, integration_start_test.go, ... is just going to muddy the waters.

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149