Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go: how to run tests for multiple packages?

I have multiple packages under a subdirectory under src/, running the tests for each package with go test is working fine.

When trying to run all tests with go test ./... the tests are running but it fails..

the tests are running against local database servers, each test file has global variables with db pointers.

I tried to run the tests with -parallel 1 to prevent contention in the db, but the tests still fail.

what can be the issue here?

EDIT: some tests are failing on missing DB entries, I completely clear the DB before and after each test. the only reason I can think of why this is happening is because of some contention between tests.

EDIT 2:

each one of my test files has 2 global variables (using mgo):

var session *mgo.Session
var db *mgo.Database

also it has the following setup and teardown functions:

func setUp() {
   s, err := cfg.GetDBSession()
   if err != nil {
       panic(err)
   }

   session = s

   db = cfg.GetDB(session)

   db.DropDatabase()
}

func tearDown() {
   db.DropDatabase()

   session.Close()
}

each tests startup with setUp() and defer tearDown()

also cfg is:

package cfg

import (
    "labix.org/v2/mgo"
)

func GetDBSession() (*mgo.Session, error) {
    session, err := mgo.Dial("localhost")

    return session, err
}

func GetDB(session *mgo.Session) *mgo.Database {
    return session.DB("test_db")
}

EDIT 3:

I changed cfg to use a random database, the tests passed. it seems that the tests from multiple packages are running somewhat in parallel.

is it possible to force go test to run everything sequentially across packages ?

like image 471
Gal Ben-Haim Avatar asked May 17 '14 19:05

Gal Ben-Haim


People also ask

How do I run multiple test cases in Golang?

go test : to run all _test.go files in the package. go test -v : will display the result of all test cases with verbose logging. go test -run TestFunctionName/Inputvalue= : to run the test case for specific input. Here I run the `TestSumNumbersInList` for only the 5th index of input.

Should go tests be in the same package?

Writing tests in Go requires a test file link, and this test file must always end with _test.go . By convention, Go testing files are always located in the same folder, or package, where the code they are testing resides.

Does Golang run tests in parallel?

The go test command may run tests for different packages in parallel as well, according to the setting of the -p flag. If this is not explicitly specified, the number will be the value of the GOMAXPROCS environment variable.

How do you run go test sequentially?

You may put it in the test function itself. You may put it in a package init() function, in the _test.go file itself. This will run once before execution of test functions begins. You may choose to implement a TestMain() function which will be called first and in which you may do additional setup before you call M.


1 Answers

Update: As pointed out by @Gal Ben-Haim, adding the (undocumented) go test -p 1 flag builds and tests all packages in serial. As put by the testflag usage message in the Go source code:

-p=n: build and test up to n packages in parallel

Old answer:

When running go test ./..., the tests of the different packages are in fact run in parallel, even if you set parallel=1 (only tests within a specific package are guaranteed to be run one at a time). If it is important that the packages be tested in sequence, like when there is database setup/teardown involved, it seems like the only way right now is to use the shell to emulate the behavior of go test ./..., and forcing the packages to be tested one by one.

Something like this, for example, works in Bash:

find . -name '*.go' -printf '%h\n' | sort -u | xargs -n1 -P1 go test

The command first lists all the subdirectories containing *.go files. Then it uses sort -u to list each subdirectory only once (removing duplicates). Finally all the subdirectories containing go files get fed to go test via xargs. The -P1 indicates that at most one command is to be run at a time.

Unfortunately, this is a lot uglier than just running go test ./..., but it might be acceptable if it is put into a shell script or aliased into a function that's more memorable:

function gotest(){   find $1 -name '*.go' -printf '%h\n' | sort -u | xargs -n1 -P1 go test; }

Now all tests can be run in the current directory by calling:

gotest .
like image 108
Herman Schaaf Avatar answered Sep 19 '22 15:09

Herman Schaaf