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
?
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")
}