Go test Command: Difference between revisions
(52 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
=External= | |||
* https://pkg.go.dev/cmd/go#hdr-Testing_flags | |||
=Internal= | =Internal= | ||
* [[Go_Tool#test|<tt>go</tt> Tool]] | * [[Go_Tool#test|<tt>go</tt> Tool]] | ||
* [[Go_Testing#Overview|Go Testing]] | * [[Go_Testing#Overview|Go Testing]] | ||
=Overview= | =Overview= | ||
The <code>test</code> command runs tests. The shared flags described here apply: {{Internal|Go_Tool_Shared_Flags#Overview|Shared Flags}} | The <code>test</code> command runs tests. The shared flags described here apply: {{Internal|Go_Tool_Shared_Flags#Overview|Shared Flags}} | ||
For more general details on testing in Go, see: {{Internal|Go_Testing#Overview|Go Testing}} | For more general details on testing in Go, see: {{Internal|Go_Testing#Overview|Go Testing}} | ||
=<tt>go test</tt> | =How <tt>go test</tt> Works= | ||
<code>go test</code> recompiles each package | <code>go test</code> recompiles each package specified in its command line, depending on the mode it is running in ([[#Local_Directory_Mode|local directory mode]] or [[#Package_List_Mode|package list mode]]), along with any files with names matching the file pattern <code>*_test.go</code> and creates a binary test file. The process consists in: | ||
* Creating a work directory (ex: <code>/var/folders/pf/t_bwclcn4mv3kq49ks14_12c0000gn/T/go-build60224940</code> and subdirectories). | |||
* Creating a <code>vet.cfg</code> file and running <code>go vet</code> on it. | |||
* Creating an <code>importcfg.link</code> file and running the linker on it. The output is the binary test file (<code>[...] -o $WORK/b001/pkg1.test [...]</code>). | |||
* Executing the binary test file as described in [[#Test_Execution|Test Execution]]. | |||
More details about the files that are included and compiles are available in the [[#File_Selection|File Selection]] section below. | |||
The resulted binary test file that is then executed. More details available in the [[#The_Test_Binary|The Test Binary]] section. | |||
==Local Directory Mode== | ==Local Directory Mode== | ||
<code>go test</code> runs in '''local directory mode''' when it is invoked with no package argument. In this mode, <code>go test</code> compiles the package sources and tests found in the current directory | <code>go test</code> runs in '''local directory mode''' when it is invoked with no package argument. In this mode, <code>go test</code> compiles the package sources and tests found in the current directory into a single test binary, and then runs the resulting test binary. [[#Caching|Caching]] is disabled. <font color=darkkhaki>This seems to assume there's a single package in the directory. What about [[Go_Packages#Hierarchical_(Nested)_Packages|nested packages]]?</font> After the package test finishes <font color=darkkhaki>(what if there are multiple packages?)</font>, the runtime prints a summary line with the test status ('ok', 'FAIL', package name and elapsed time). | ||
==Package List Mode== | ==Package List Mode== | ||
<code>go test</code> runs in '''package list mode''' when <code>go test</code> is invoked with explicit package arguments (ex: <code>go test math</code>), with the <code>./...</code> argument or even with <code>.</code>. In this mode the tool compiles and tests each of the packages listed on the command line. If | <code>go test</code> runs in '''package list mode''' when <code>go test</code> is invoked with explicit package arguments (ex: <code>go test math</code>), with the <code>./...</code> argument or even with <code>.</code>. In this mode the tool independently compiles and tests each of the packages listed on the command line or those implied by <code>./...</code>. Note that <code>./...</code> implies the list of packages recursively found in the current directory, and the <code>go test</code> command obtains that list executing <code>go list ./...</code>. For more details see: {{Internal|go_list#Overview|<tt>go list</tt>}} | ||
[[Go_Packages#Hierarchical_(Nested)_Packages|Nested packages]] are handled as independent packages. If all tests from a package pass, the tool prints only the final 'ok' summary line. If at least one test fails, the tool prints a full test output. Successful package test results are [[#Caching|cached]] to avoid unnecessary repeated running of the test. | |||
=File Selection= | =File Selection= | ||
Line 21: | Line 35: | ||
<code>go test</code> will ignore a directory named "testdata", making it available to hold ancillary data needed by the tests. | <code>go test</code> will ignore a directory named "testdata", making it available to hold ancillary data needed by the tests. | ||
More details on writing <code>*_test.go</code> files are available in: {{Internal|Go_Testing#Write_a_Unit_Test|Go Testing | Write a Unit Test}} | |||
==Skipping Certain Packages when Running Tests in Package List Mode== | |||
<syntaxhighlight lang='bash'> | |||
go test $(go list ./... | grep -v /something/) | |||
</syntaxhighlight> | |||
==<span id='Skipping_Certain_Files_when_Running_Tests'></span>Specifying which Tests to Run== | |||
One option is to use build tags: | |||
{{Internal|Go_Build_Tags#Controlling_Test_Execution_with_Build_Tags|Controlling Test Execution with Build Tags}} | |||
Another option is to use the test name and the <code>go test -run <regex></code> command line option: | |||
{{Internal|Go_test_Command#-run|<tt>go test</tt> <tt>-run</tt> Option}} | |||
=The Test Binary= | =The Test Binary= | ||
For each package, <code>go test</code> compiles the package and it links it together with its dependencies into a test binary file named <code><package-name>.test</code> (example: <code>$WORK/b391/scheduler.test</code>). | |||
As part of building a test binary, go test runs <code>go vet</code> on the package and its test source files to identify significant problems. If <code>go vet</code> finds any problems, <code>go test reports</code> those and does not run the test binary. Only a high-confidence subset of the default <code>go vet</code> checks are used. That subset is: atomic, bool, buildtags, directive, errorsas, ifaceassert, nilfunc, printf, and stringintconv. | As part of building a test binary, go test runs <code>go vet</code> on the package and its test source files to identify significant problems. If <code>go vet</code> finds any problems, <code>go test reports</code> those and does not run the test binary. Only a high-confidence subset of the default <code>go vet</code> checks are used. That subset is: atomic, bool, buildtags, directive, errorsas, ifaceassert, nilfunc, printf, and stringintconv. | ||
=Test Execution= | =Test Execution= | ||
The [[#The_Test_Binary|test binary file]] is executed as such (run <code>go test</code> with <code>-v -x</code> to get this output): | |||
<syntaxhighlight lang='bash'> | |||
$WORK/b001/pkg1.test -test.paniconexit0 -test.timeout=10m0s -test.v=true -test.count=1 | |||
</syntaxhighlight> | |||
All test output and summary lines are printed to the go command's standard output, even if the test printed them to its own standard error. The go command's standard error is reserved for printing errors building the tests. | All test output and summary lines are printed to the go command's standard output, even if the test printed them to its own standard error. The go command's standard error is reserved for printing errors building the tests. | ||
==Individual Test Function Execution Order== | |||
The individual test functions are executed in the order they're declared in the <code>*_test.go</code> file. | |||
If the test functions are specified in more than one <code>*_test.go</code> files, the files are sorted in alphabetical order and their tests are executed in that order. Inside a file, the individual test functions are executed in the order they're declared in the file. | |||
==Do Additional Tasks before a Test Function is Run== | |||
* Put the initialization tasks in a <code>init()</code> function in the <code>_test.go</code> file. This will run once before the execution of the test functions begins: | |||
<syntaxhighlight lang='go'> | |||
package pkg1 | |||
[...] | |||
func init() { | |||
} | |||
</syntaxhighlight> | |||
<font color=darkkhaki> | |||
* Put the task in <code>TestMain()</code> function https://pkg.go.dev/testing#pkg-overview that will be called first and in which you may do additional setup before you call <code>M.Run()</code> http://golang.org/pkg/testing/#M.Run to trigger the execution of test function. | |||
</font> | |||
=Caching= | =Caching= | ||
Line 36: | Line 90: | ||
To disable test caching, use any test flag or argument other than the cacheable flags. The idiomatic way to disable test caching explicitly is to use <code>-count=1</code>. | To disable test caching, use any test flag or argument other than the cacheable flags. The idiomatic way to disable test caching explicitly is to use <code>-count=1</code>. | ||
<code>go tool</code> reports whether a test result was cached by appending <code>(cached)</code> to the output: | |||
<font size=-2> | |||
ok example.com/experimental-go-module/internal/pkg1 (cached) | |||
</font> | |||
=Test Coverage= | |||
{{External|https://medium.com/illumination/a-full-guide-on-coverage-in-golang-95164cdddcd9}} | |||
<syntaxhighlight lang='bash'> | |||
go test ./... -count 1 -cover -coverprofile=./build/coverage.out | |||
go tool cover -html=./build/coverage.out -o ./build/coverage.html | |||
go tool covdata percent -i=./build/coverage.out | |||
</syntaxhighlight> | |||
<font color=darkkhaki>TO PROCESS: https://go.dev/blog/integration-test-coverage#working-with-coverage-data-files</font> | |||
Also see: {{Internal|Go_Testing#Code_Coverage_for_Integration_Tests|Code Coverage for Integration Tests}} | |||
=Options= | =Options= | ||
Line 43: | Line 114: | ||
==<tt>-json</tt>== | ==<tt>-json</tt>== | ||
==<tt>-o file</tt>== | ==<tt>-o file</tt>== | ||
==<tt>-cover</tt>== | |||
See [[#Test_Coverage|Test Coverage]] above. | |||
==<tt>-ldflags</tt>== | |||
See: {{Internal|Go_build#-ldflags|<tt>go build -ldflags</tt>}} | |||
==<tt>-tags</tt>== | |||
See: {{Internal|Go_Build_Tags#Overview|Build Tags}} | |||
==<tt>-run</tt>== | |||
This option allows [[Go_test_Command#Specifying_which_Tests_to_Run|controlling which tests to run]] based on their names. | |||
For tests, the regular expression is split by unbracketed slash (/) characters into a sequence of regular expressions, and each part of a test's identifier must match the corresponding element in the sequence, if any. Note that possible parents of matches are run too, so that <code>-run=X/Y </code> matches and runs and reports the result of all tests matching X, even those without sub-tests matching Y, because it must run them to look for those sub-tests. | |||
<font color=darkkhaki>TO PROCESS: https://peter.bourgon.org/blog/2021/04/02/dont-use-build-tags-for-integration-tests.html</font> | |||
==<tt>-skip</tt>== | |||
-skip regexp | |||
Run only those tests, examples, fuzz tests, and benchmarks that do not match the regular expression. Like for -run and -bench, for tests and benchmarks, the regular expression is split by unbracketed slash (/) characters into a sequence of regular expressions, and each part of a test's identifier must match the corresponding element in the sequence, if any. | |||
==<tt>-timeout</tt>== | |||
-timeout d | |||
If a test binary runs longer than duration <code>d</code>, panic. If <code>d</code> is 0, the timeout is disabled. The default is 10 minutes ("10m"). | |||
The duration can be specified as "ns", "us" (or "µs"), "ms", "s", "m", "h". See: {{Internal|Go_Package_time#Duration|Duration}} |
Latest revision as of 00:37, 13 March 2024
External
Internal
Overview
The test
command runs tests. The shared flags described here apply:
For more general details on testing in Go, see:
How go test Works
go test
recompiles each package specified in its command line, depending on the mode it is running in (local directory mode or package list mode), along with any files with names matching the file pattern *_test.go
and creates a binary test file. The process consists in:
- Creating a work directory (ex:
/var/folders/pf/t_bwclcn4mv3kq49ks14_12c0000gn/T/go-build60224940
and subdirectories). - Creating a
vet.cfg
file and runninggo vet
on it. - Creating an
importcfg.link
file and running the linker on it. The output is the binary test file ([...] -o $WORK/b001/pkg1.test [...]
). - Executing the binary test file as described in Test Execution.
More details about the files that are included and compiles are available in the File Selection section below.
The resulted binary test file that is then executed. More details available in the The Test Binary section.
Local Directory Mode
go test
runs in local directory mode when it is invoked with no package argument. In this mode, go test
compiles the package sources and tests found in the current directory into a single test binary, and then runs the resulting test binary. Caching is disabled. This seems to assume there's a single package in the directory. What about nested packages? After the package test finishes (what if there are multiple packages?), the runtime prints a summary line with the test status ('ok', 'FAIL', package name and elapsed time).
Package List Mode
go test
runs in package list mode when go test
is invoked with explicit package arguments (ex: go test math
), with the ./...
argument or even with .
. In this mode the tool independently compiles and tests each of the packages listed on the command line or those implied by ./...
. Note that ./...
implies the list of packages recursively found in the current directory, and the go test
command obtains that list executing go list ./...
. For more details see:
Nested packages are handled as independent packages. If all tests from a package pass, the tool prints only the final 'ok' summary line. If at least one test fails, the tool prints a full test output. Successful package test results are cached to avoid unnecessary repeated running of the test.
File Selection
Upon execution, go test
identifies all files that match the *_test.go
pattern and compiles them along the package files. These files may contain test functions, benchmark functions, fuzz tests and example functions.
Files whose name begins with "_" (including "_test.go") or "." are ignored.
Test files that declare a package with the suffix "_test" will be compiled as a separate package, and then linked and run with the main test binary.
go test
will ignore a directory named "testdata", making it available to hold ancillary data needed by the tests.
More details on writing *_test.go
files are available in:
Skipping Certain Packages when Running Tests in Package List Mode
go test $(go list ./... | grep -v /something/)
Specifying which Tests to Run
One option is to use build tags:
Another option is to use the test name and the go test -run <regex>
command line option:
The Test Binary
For each package, go test
compiles the package and it links it together with its dependencies into a test binary file named <package-name>.test
(example: $WORK/b391/scheduler.test
).
As part of building a test binary, go test runs go vet
on the package and its test source files to identify significant problems. If go vet
finds any problems, go test reports
those and does not run the test binary. Only a high-confidence subset of the default go vet
checks are used. That subset is: atomic, bool, buildtags, directive, errorsas, ifaceassert, nilfunc, printf, and stringintconv.
Test Execution
The test binary file is executed as such (run go test
with -v -x
to get this output):
$WORK/b001/pkg1.test -test.paniconexit0 -test.timeout=10m0s -test.v=true -test.count=1
All test output and summary lines are printed to the go command's standard output, even if the test printed them to its own standard error. The go command's standard error is reserved for printing errors building the tests.
Individual Test Function Execution Order
The individual test functions are executed in the order they're declared in the *_test.go
file.
If the test functions are specified in more than one *_test.go
files, the files are sorted in alphabetical order and their tests are executed in that order. Inside a file, the individual test functions are executed in the order they're declared in the file.
Do Additional Tasks before a Test Function is Run
- Put the initialization tasks in a
init()
function in the_test.go
file. This will run once before the execution of the test functions begins:
package pkg1
[...]
func init() {
}
- Put the task in
TestMain()
function https://pkg.go.dev/testing#pkg-overview that will be called first and in which you may do additional setup before you callM.Run()
http://golang.org/pkg/testing/#M.Run to trigger the execution of test function.
Caching
The rule for a cache hit is that TODO.
Cacheable test flags: -benchtime
, -cpu
, -list
, -parallel
, -run
, -short
, -timeout
, -failfast
and -v
.
To disable test caching, use any test flag or argument other than the cacheable flags. The idiomatic way to disable test caching explicitly is to use -count=1
.
go tool
reports whether a test result was cached by appending (cached)
to the output:
ok example.com/experimental-go-module/internal/pkg1 (cached)
Test Coverage
go test ./... -count 1 -cover -coverprofile=./build/coverage.out
go tool cover -html=./build/coverage.out -o ./build/coverage.html
go tool covdata percent -i=./build/coverage.out
TO PROCESS: https://go.dev/blog/integration-test-coverage#working-with-coverage-data-files
Also see:
Options
-args
-c
-exec xprog
-json
-o file
-cover
See Test Coverage above.
-ldflags
See:
-tags
See:
-run
This option allows controlling which tests to run based on their names.
For tests, the regular expression is split by unbracketed slash (/) characters into a sequence of regular expressions, and each part of a test's identifier must match the corresponding element in the sequence, if any. Note that possible parents of matches are run too, so that -run=X/Y
matches and runs and reports the result of all tests matching X, even those without sub-tests matching Y, because it must run them to look for those sub-tests.
TO PROCESS: https://peter.bourgon.org/blog/2021/04/02/dont-use-build-tags-for-integration-tests.html
-skip
-skip regexp
Run only those tests, examples, fuzz tests, and benchmarks that do not match the regular expression. Like for -run and -bench, for tests and benchmarks, the regular expression is split by unbracketed slash (/) characters into a sequence of regular expressions, and each part of a test's identifier must match the corresponding element in the sequence, if any.
-timeout
-timeout d
If a test binary runs longer than duration d
, panic. If d
is 0, the timeout is disabled. The default is 10 minutes ("10m").
The duration can be specified as "ns", "us" (or "µs"), "ms", "s", "m", "h". See: