-1

I am using the built-in testing module to run some functional tests I have in my GO project. In my project I have external dependencies, which I connect to in my TestMain method. I save these connections to variables which then I use in the tests themselves, and the connections can take a long time to establish properly (Kafka anyone?). I would like to run the tests on-demand, but after these variables have been setup.

So what I want is to listen to stdin in my TestMain function and either run or quit the tests. But I want it to be controlled by the user so I can have my test environment setup, and the tests will run on my command.

But sadly, it seems that when running go test ... that stdin is mapped directly to /dev/null. So when I try to read os.Stdin I get an EOF error. The minimum code for this is:

package tests

import (
    "bufio"
    "fmt"
    "os"
    "testing"
)

func TestMain(m *testing.M) {
    reader := bufio.NewReader(os.Stdin)
    if input, err := reader.ReadString('\n'); err != nil {
        fmt.Println(err)
        fmt.Println("-----------")
        fmt.Println(input)
        os.Exit(1)
    }
    fmt.Println("ESCAPED!")
    os.Exit(m.Run())
}

I have read in circles how to mock this for unit tests and the sort, but my case is more of a functional test runner. Is there a way, or even some trickery, that will allow me to open or change the test processes stdin?

shiznatix
  • 11
  • 4
  • "So what I want is to listen to stdin in my TestMain function and either run or quit the tests." Don't do that. Use a environment variable or a command line flag to control whether to run or skip a test. Reading from stdin is a bad idea for this kind of control. Using a command line flag has the added benefit that it is self-documenting. – Volker Aug 24 '20 at 13:28
  • This isn't about skipping tests, its about holding connections to things like Kafka and running the tests with these connections still alive. The issue to solve is that establishing these connections takes a long time (~15sec) and this is very annoying to do every time you run the tests. I want to establish the connections, then run the tests over and over (on demand of course) without re-establishing the connections. – shiznatix Aug 25 '20 at 06:57

1 Answers1

0

You can redirect os.Stdin, it depends on OS though:

package tests

import (
    "fmt"
        "os"
        "testing"
    "bufio"
    "runtime"
)

func TestMain(m *testing.M) {

    var ttyName string
    if runtime.GOOS == "windows" {
        ttyName = "con"
    } else {
        ttyName = "/dev/tty"
    }   

    f, err := os.Open(ttyName)
    if err != nil {
        panic(err)
    }
    defer f.Close()

    oldStdin := os.Stdin
    defer func() { os.Stdin = oldStdin }()

    os.Stdin = f

    reader := bufio.NewReader(os.Stdin)
        if input, err := reader.ReadString('\n'); err != nil {
        fmt.Println("Error:", err)
        fmt.Println("-----------")
        fmt.Println(input)
        os.Exit(1)
    }
    fmt.Println("ESCAPED!")
    os.Exit(m.Run())
}

func TestHello(t *testing.T){
    fmt.Println("Hello")
}
maxim_ge
  • 1,153
  • 1
  • 10
  • 18