在非主程序包中运行主程序

We have a package with a fair number of complex tests. As part of the test suite, they run on builds etc.

 func TestFunc(t *testing.T) {
    //lots of setup stuff and defining success conditions
    result := SystemModel.Run()
 }

Now, for one of these tests, I want to introduce some kind of frontend which will make it possible for me to debug a few things. It's not really a test, but a debug tool. For this, I want to just run the same test but with a Builder pattern:

 func TestFuncWithFrontend(t *testing.T) {
    //lots of setup stuff and defining success conditions
    result := SystemModel.Run().WithHTTPFrontend(":9999")
 }

The test then would only start if I send a signal via HTTP from the frontend. Basically WithHTTPFrontend() just waits with a channel on a HTTP call from the frontend.

This of course would make the automated tests fail, because no such signal will be sent and execution will hang.

I can't just rename the package to main because the package has 15 files and they are used elsewhere in the system.

Likewise I haven't found a way to run a test only on demand while excluding it from the test suite, so that TestFuncWithFrontend would only run from the commandline - I don't care if with go run or go test or whatever.

I've also thought of ExampleTestFunc() but there's so much output produced by the test it's useless, and without defining Output: ..., the Example won't run.

Unfortunately, there's also a lot of initialization code at (private, i.e. lower case) package level that the test needs. So I can't just create a sub-package main, as a lot of that stuff wouldn't be accessible.

It seems I have three choices:

  1. Export all this initialization variables and code with upper case, so that I could be using it from a sub-main package

  2. Duplicate the whole code.

  3. Move the test into a sub-package main and then have a func main() for the test with Frontend and a _test.go for the normal test, which would have to import a few things from the parent package.

I'd rather like to avoid the second option...And the first is better, but isn't great either IMHO. I think I'll go for the third, but...

am I missing some other option?

I finally found an acceptable option. This answer

Skip some tests with go test

brought me to the right track.

Essentially using build tags which would not be present in normal builds but which I can provide when executing manually.

You can pass a custom command line argument to go test and start the debug port based on that. Something like this:

package hello_test

import (
    "flag"
    "log"
    "testing"
)

var debugTest bool

func init() {
    flag.BoolVar(&debugTest, "debug-test", false, "Setup debugging for tests")
}

func TestHelloWorld(t *testing.T) {
    if debugTest {
        log.Println("Starting debug port for test...")
        // Start the server here
    }

    log.Println("Done")
}

Then if you want to run just that specific test, go test -debug-test -run '^TestHelloWorld$' ./.

Alternatively it's also possible to set a custom environment variable that you check in the test function to change behaviour.