I want to write an integration test which tests writing and reading data to and from a database. In order to do this, I need my first test function to connect and prepare a test database; and if that is a success, let the other tests run, which will then be doing queries on it.
So I implemented a TestMain(m *testing.M)
which creates a database and runs migrations on it, and if there's no errors, I run m.Run()
.
But it doesn't have any m.Print
or m.Fatal
methods like testing.T
does. And if I try to log something with log.Print()
, it doesn't get output (probably because no testing could have been properly marked as failing).
And the reason why I don't like the creation of the database with a regular test function, is because a regular test of course cannot stop other tests from running, so all my other tests from that file will run and plague the output messages, since they will all fail.
So how do I log something out from TestMain? My TestMain can still fail in multiple ways, and i would like to see in the output what it was.
Example to show TestMain
's output not being displayed:
$ ls
go.mod main_test.go
$ cat go.mod
module App
go 1.16
$ cat main_test.go
package main
import (
"testing"
"log"
)
func TestMain(m *testing.M) {
log.Print("hello")
}
$ go test ./.
ok App 0.147s
$
CodePudding user response:
You need the -v
flag:
go test -v .
Note: .
is equivalent to ./.
If you want to run tests on all sub-directories use ./...
like so:
go test -v ./...
Why is this? Since you are running tests in what's call package list mode (i.e. ./.
) - from the docs in go help test
:
In this (package list) mode, go test compiles and tests each of the packages listed on the command line. If a package test passes, go test prints only the final 'ok' summary line. If a package test fails, go test prints the full test output.
This is the behavior you have noted. Reading further:
... If invoked with the -bench or -v flag, go test prints the full output even for passing package tests, in order to display the requested benchmark results or verbose logging.
Note: go test
alone (i.e. no package list) will allow output logging from TestMain
like log.Print
.
EDIT here's how I typically do pre-flight setup for my tests:
var testDB *pgxpool.Pool // all tests should use this
func createDBconn() (*pgxpool.Pool, error) {
// read ENV VARs - establish connection
// ...
return dbconn, nil
}
func TestMain(m *testing.M) {
var err error
testDB, err = createDBconn()
if err != nil {
log.Fatal(err)
}
// call flag.Parse() here if TestMain uses flags
os.Exit(m.Run())
}
if any of the prep fails, then log.Fatal
ensures the reason is logged & the program terminates.
CodePudding user response:
It seems that messages printed with log.Print()
will display if the test exits with a non-zero code, so this situation is best solved by exiting with non-zero right after the log line, like so:
log.Print("setup of database has failed")
os.Exit(1)