231

I want to create a package in Go with tests and examples for the package as subdirectories to keep the workspace cleaner. Is this possible and if so how?

All the documentation always puts the testing code in the same place as the other code, is this better in some way or just convention?

Carson
  • 6,105
  • 2
  • 37
  • 45
The Graceful Penguin
  • 2,424
  • 2
  • 14
  • 7
  • 15
    Note: `go test ./...` will run tests on the current folder *and* all subfolders. See [my answer below](http://stackoverflow.com/a/21725603/6309) – VonC Feb 12 '14 at 11:42
  • Possible duplicate of [How to \`go test\` all testings in my project?](http://stackoverflow.com/questions/16353016/how-to-go-test-all-testings-in-my-project) – Matthew Rankin Dec 04 '15 at 17:07
  • 1
    i was thinking the same thing. having trouble putting tests n a seperate dir because diretor on the same level have sub dirs. – filthy_wizard Jul 13 '16 at 21:59

4 Answers4

374

Note that you can run go test "recursively": you need to list all the packages you want to test.

If you are in the root folder of your Go project, type:

go test ./...

The './...' notation is described in the section "Description of package lists" of the "command go":

An import path is a pattern if it includes one or more "..." wildcards, each of which can match any string, including the empty string and strings containing slashes.

Such a pattern expands to all package directories found in the GOPATH trees with names matching the patterns.

As a special case, x/... matches x as well as x's subdirectories.
For example, net/... expands to net and packages in its subdirectories.


If you keep your _test.go files in a subfolder, the 'go test ./...' command will be able to pick them up.
But:

  • you will need to prefix your exported variables and functions (used in your tests) with the name of your package, in order for the test file to be able to access the package exported content.
  • you wouldn't access non-exported content.

That being said, I would still prefer to keep the _test.go file right beside the main source file: it is easier to find.


2022: For code coverage:

go test -coverpkg=./... ./...

See "How to plot Go test coverage over time" from Frédéric G. MARAND and fgmarand/gocoverstats to produce aggregate coverage statistics for CI integration of Go projects.

Also, go-cover-treemap.io is fun.


March 2023: As documented in "Code coverage for Go integration tests":

With the 1.20 release, Go’s coverage tooling is no longer limited to package tests, but supports collecting profiles from larger integration tests.

Example:

$ go build -cover -o myprogram.exe myprogram.go
$ mkdir somedata
$ GOCOVERDIR=somedata ./myprogram.exe
I say "Hello, world." and "see ya"
$ ls somedata
covcounters.c6de772f99010ef5925877a7b05db4cc.2424989.1670252383678349347
covmeta.c6de772f99010ef5925877a7b05db4cc

See Go 1.20 Cover.


As noted by kbolino in the comments:

You can put your tests in a separate package without putting them in a separate directory.
Test files for package foo can be in package foo_test and still be in the same directory, while also not having any access to unexported (private) members of package foo.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 5
    Some might argue non-access to private stuff is normal black-box testing and better. Regarding having to qualify public symbols, you can always import _ "...". – ddevienne May 29 '15 at 12:57
  • 1
    I found that `go test ./...` doesn't work well if (a) you have tests in a separate folder, and (b) you want to measure code coverage. For some reason, code coverage misses the package under test – Maria Ines Parnisari Jun 10 '22 at 22:35
  • @MariaInesParnisari Interresting. I doscovered https://go-cover-treemap.io/ recently. Also https://osinet.fr/go/en/articles/plotting-go-test-coverage/ can help. – VonC Jun 11 '22 at 09:23
  • i had to add `-coverpkg=./...` and it worked! – Maria Ines Parnisari Jun 13 '22 at 03:49
  • @MariaInesParnisari Do you mean as in `go test -coverpkg=./... ./...`? Or just `go test -coverpkg=./...`? – VonC Jun 13 '22 at 09:28
  • It is probably worth noting that you can put your tests in a separate _package_ without putting them in a separate _directory_. Test files for package `foo` can be in package `foo_test` and still be in the same directory, while also not having any access to unexported (private) members of package `foo`. – kbolino Mar 13 '23 at 17:29
23

EDITED

Built on VonC's answer,

This answer is valid in go1.11. No yet tested in upper go versions.

For those of you who like to keep their tests in a sub-folder, say test, then running

go test ./...

will attempt to run tests in every folder, even those that do not contain any test, thus having a ? in the subsequent report for non-test folders.

Running

go test ./.../test

instead will target only your test folders, thus having a clean report focused on your tests folders only.

CAUTION

Please be mindful that using test sub-folders will prevent coverage report computation. The phylosophy of go is to leave test files in the package folders.

avi.elkharrat
  • 6,100
  • 6
  • 41
  • 47
  • dear anna, please explain what does not work? and what is your version of go? what are you trying to do? I realized afterwards that this method does not allowed to compute code coverage, which is a pitty. Is this what you mean? – avi.elkharrat Jan 14 '20 at 09:23
  • 4
    `go test ./.../test` returns `go: warning: "./.../test" matched no packages` // does not only target test folders. go version go1.13 darwin/amd64 – anna Jan 14 '20 at 17:28
  • I don't know about `go1.13`. I should precise that this answer my answer is valid in `go1.11`. – avi.elkharrat Jan 14 '20 at 19:53
  • 1
    @Madeo, this would make sens, because golang does not encourage segregation of tests and code. The anomaly was to allow it in previous versions. – avi.elkharrat Feb 15 '20 at 20:32
  • 1
    @avi.elkharrat and in fact I have decided to not purse this approach anymore, even though I liked to keep my tests into a separate package/folder =( – Matteo Feb 16 '20 at 01:20
  • @Madeo, same here dude. I like the java / maven style better, but it does not work like this in `Go`. Code coverage is more important than personal preferences, i guess. – avi.elkharrat Feb 16 '20 at 10:12
  • so go seems still broken as of 2022, i would like to segregate my tests but can't seem to find a good way to do so – Sidharth Ghoshal Apr 28 '22 at 00:59
  • Run `go test ./tests/...` to run go test only within `tests/` folder. – Saurabh Feb 16 '23 at 10:44
20

Put your tests alongside your code in the same directory in a file called file_test.go where "file" is the name of the source code file you're testing. This is convention and I've found it to be best in my own experience.

If the go test tool isn't quite automated enough for you, you might look into GoConvey, which has a web UI that will automatically update and run traditional Go tests as well as GoConvey tests (which are based on behavior, and are more self-documenting than traditional Go tests).

Matt
  • 22,721
  • 17
  • 71
  • 112
  • 2
    GoConvey is awesome (and I am waiting for the new UI with high anticipation). I am using it in my current project as in https://github.com/VonC/asciidocgo/blob/master/abstractNode_test.go , for instance). However, `go test` can also work for subfolders. See [my answer below](http://stackoverflow.com/a/21725603/6309) – VonC Feb 12 '14 at 11:42
  • Right you are. In fact, it's probably more relevant than my answer for this question. – Matt Feb 12 '14 at 14:30
-7

I normally don't do test, but you can group your file into directories and use import like

import "./models" if is one level out
import "../models if is one level out and one level in

For example, for:
./models/todo.go
./test/todo_test.go

to test todo.go from todo_test.go, your import in the todo_test.go will be

import "../models"

kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • This method of importing the code only works for exposed functions. It does not seem to behave like they are in the same package even thought you explicitly put them in the same package. So this solution does not really solve the problem for unit testing. – The Graceful Penguin Oct 09 '13 at 01:41