cmd/go: add -args to 'go test' to resolve -v ambiguity

The new flag -args stops flag processing, leaving the rest of the command line
to be passed to the underlying test binary verbatim. Thus, both of these pass
a literal -v -n on the test binary command line, without putting the go command
into verbose mode or disabling execution of commands:

	go test . -args -v -n
	go test -args -v -n

Also try to make the documentation a bit clearer.

Fixes #7221.
Fixes #12177.

Change-Id: Ief9e830a6fbb9475d96011716a86e2524a35eceb
Reviewed-on: https://go-review.googlesource.com/17775
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Russ Cox 2015-12-14 11:04:03 -05:00
parent 5c596b51fd
commit 8350e06556
4 changed files with 126 additions and 42 deletions

View File

@ -660,7 +660,7 @@ Test packages
Usage: Usage:
go test [-c] [-i] [build and test flags] [packages] [flags for test binary] go test [build/test flags] [packages] [build/test flags & test binary flags]
'Go test' automates testing the packages named by the import paths. 'Go test' automates testing the packages named by the import paths.
It prints a summary of the test results in the format: It prints a summary of the test results in the format:
@ -690,10 +690,16 @@ non-test installation.
In addition to the build flags, the flags handled by 'go test' itself are: In addition to the build flags, the flags handled by 'go test' itself are:
-args
Pass the remainder of the command line (everything after -args)
to the test binary, uninterpreted and unchanged.
Because this flag consumes the remainder of the command line,
the package list (if present) must appear before this flag.
-c -c
Compile the test binary to pkg.test but do not run it Compile the test binary to pkg.test but do not run it
(where pkg is the last element of the package's import path). (where pkg is the last element of the package's import path).
The file name can be changed with the -o flag. The file name can be changed with the -o flag.
-exec xprog -exec xprog
Run the test binary using xprog. The behavior is the same as Run the test binary using xprog. The behavior is the same as
@ -704,17 +710,12 @@ In addition to the build flags, the flags handled by 'go test' itself are:
Do not run the test. Do not run the test.
-o file -o file
Compile the test binary to the named file. Compile the test binary to the named file.
The test still runs (unless -c or -i is specified). The test still runs (unless -c or -i is specified).
The test binary also accepts flags that control execution of the test; these The test binary also accepts flags that control execution of the test; these
flags are also accessible by 'go test'. See 'go help testflag' for details. flags are also accessible by 'go test'. See 'go help testflag' for details.
If the test binary needs any other flags, they should be presented after the
package names. The go tool treats as a flag the first argument that begins with
a minus sign that it does not recognize itself; that argument and all subsequent
arguments are passed as arguments to the test binary.
For more about build flags, see 'go help build'. For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'. For more about specifying packages, see 'go help packages'.
@ -1442,25 +1443,58 @@ control the execution of any test:
Verbose output: log all tests as they are run. Also print all Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds. text from Log and Logf calls even if the test succeeds.
The test binary, called pkg.test where pkg is the name of the Each of these flags is also recognized with an optional 'test.' prefix,
directory containing the package sources, can be invoked directly as in -test.v. When invoking the generated test binary (the result of
after building it with 'go test -c'. When invoking the test binary 'go test -c') directly, however, the prefix is mandatory.
directly, each of the standard flag names must be prefixed with 'test.',
as in -test.run=TestMyFunc or -test.v.
When running 'go test', flags not listed above are passed through The 'go test' command rewrites or removes recognized flags,
unaltered. For instance, the command as appropriate, both before and after the optional package list,
before invoking the test binary.
go test -x -v -cpuprofile=prof.out -dir=testdata -update For instance, the command
go test -v -myflag testdata -cpuprofile=prof.out -x
will compile the test binary and then run it as will compile the test binary and then run it as
pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
(The -x flag is removed because it applies only to the go command's
execution, not to the test itself.)
The test flags that generate profiles (other than for coverage) also The test flags that generate profiles (other than for coverage) also
leave the test binary in pkg.test for use when analyzing the profiles. leave the test binary in pkg.test for use when analyzing the profiles.
Flags not recognized by 'go test' must be placed after any specified packages. The command-line package list, if present, must appear before any
flag not known to the go test command. Continuing the example above,
the package list would have to appear before -myflag, but could appear
on either side of -v.
To keep an argument for a test binary from being interpreted as a
known flag or a package name, use -args (see 'go help test') which
passes the remainder of the command line through to the test binary
uninterpreted and unaltered.
For instance, the command
go test -v -args -x -v
will compile the test binary and then run it as
pkg.test -test.v -x -v
Similarly,
go test -args math
will compile the test binary and then run it as
pkg.test math
In the first example, the -x and the second -v are passed through to the
test binary unchanged and with no effect on the go command itself.
In the second example, the argument math is passed through to the test
binary, instead of being interpreted as the package list.
Description of testing functions Description of testing functions

View File

@ -1983,6 +1983,13 @@ func TestGoTestFooTestWorks(t *testing.T) {
tg.run("test", "testdata/standalone_test.go") tg.run("test", "testdata/standalone_test.go")
} }
func TestGoTestFlagsAfterPackage(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.run("test", "testdata/flag_test.go", "-v", "-args", "-v=7") // Two distinct -v flags.
tg.run("test", "-v", "testdata/flag_test.go", "-args", "-v=7") // Two distinct -v flags.
}
func TestGoTestXtestonlyWorks(t *testing.T) { func TestGoTestXtestonlyWorks(t *testing.T) {
tg := testgo(t) tg := testgo(t)
defer tg.cleanup() defer tg.cleanup()

View File

@ -32,7 +32,7 @@ func init() {
cmdTest.Run = runTest cmdTest.Run = runTest
} }
const testUsage = "test [-c] [-i] [build and test flags] [packages] [flags for test binary]" const testUsage = "test [build/test flags] [packages] [build/test flags & test binary flags]"
var cmdTest = &Command{ var cmdTest = &Command{
CustomFlags: true, CustomFlags: true,
@ -67,11 +67,6 @@ non-test installation.
` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details. ` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details.
If the test binary needs any other flags, they should be presented after the
package names. The go tool treats as a flag the first argument that begins with
a minus sign that it does not recognize itself; that argument and all subsequent
arguments are passed as arguments to the test binary.
For more about build flags, see 'go help build'. For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'. For more about specifying packages, see 'go help packages'.
@ -82,10 +77,16 @@ See also: go build, go vet.
const testFlag1 = ` const testFlag1 = `
In addition to the build flags, the flags handled by 'go test' itself are: In addition to the build flags, the flags handled by 'go test' itself are:
-args
Pass the remainder of the command line (everything after -args)
to the test binary, uninterpreted and unchanged.
Because this flag consumes the remainder of the command line,
the package list (if present) must appear before this flag.
-c -c
Compile the test binary to pkg.test but do not run it Compile the test binary to pkg.test but do not run it
(where pkg is the last element of the package's import path). (where pkg is the last element of the package's import path).
The file name can be changed with the -o flag. The file name can be changed with the -o flag.
-exec xprog -exec xprog
Run the test binary using xprog. The behavior is the same as Run the test binary using xprog. The behavior is the same as
@ -96,8 +97,8 @@ In addition to the build flags, the flags handled by 'go test' itself are:
Do not run the test. Do not run the test.
-o file -o file
Compile the test binary to the named file. Compile the test binary to the named file.
The test still runs (unless -c or -i is specified). The test still runs (unless -c or -i is specified).
The test binary also accepts flags that control execution of the test; these The test binary also accepts flags that control execution of the test; these
flags are also accessible by 'go test'. flags are also accessible by 'go test'.
@ -229,25 +230,58 @@ const testFlag2 = `
Verbose output: log all tests as they are run. Also print all Verbose output: log all tests as they are run. Also print all
text from Log and Logf calls even if the test succeeds. text from Log and Logf calls even if the test succeeds.
The test binary, called pkg.test where pkg is the name of the Each of these flags is also recognized with an optional 'test.' prefix,
directory containing the package sources, can be invoked directly as in -test.v. When invoking the generated test binary (the result of
after building it with 'go test -c'. When invoking the test binary 'go test -c') directly, however, the prefix is mandatory.
directly, each of the standard flag names must be prefixed with 'test.',
as in -test.run=TestMyFunc or -test.v.
When running 'go test', flags not listed above are passed through The 'go test' command rewrites or removes recognized flags,
unaltered. For instance, the command as appropriate, both before and after the optional package list,
before invoking the test binary.
go test -x -v -cpuprofile=prof.out -dir=testdata -update For instance, the command
go test -v -myflag testdata -cpuprofile=prof.out -x
will compile the test binary and then run it as will compile the test binary and then run it as
pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
(The -x flag is removed because it applies only to the go command's
execution, not to the test itself.)
The test flags that generate profiles (other than for coverage) also The test flags that generate profiles (other than for coverage) also
leave the test binary in pkg.test for use when analyzing the profiles. leave the test binary in pkg.test for use when analyzing the profiles.
Flags not recognized by 'go test' must be placed after any specified packages. The command-line package list, if present, must appear before any
flag not known to the go test command. Continuing the example above,
the package list would have to appear before -myflag, but could appear
on either side of -v.
To keep an argument for a test binary from being interpreted as a
known flag or a package name, use -args (see 'go help test') which
passes the remainder of the command line through to the test binary
uninterpreted and unaltered.
For instance, the command
go test -v -args -x -v
will compile the test binary and then run it as
pkg.test -test.v -x -v
Similarly,
go test -args math
will compile the test binary and then run it as
pkg.test math
In the first example, the -x and the second -v are passed through to the
test binary unchanged and with no effect on the go command itself.
In the second example, the argument math is passed through to the test
binary, instead of being interpreted as the package list.
` `
var helpTestfunc = &Command{ var helpTestfunc = &Command{

View File

@ -87,6 +87,7 @@ func init() {
func testFlags(args []string) (packageNames, passToTest []string) { func testFlags(args []string) (packageNames, passToTest []string) {
inPkg := false inPkg := false
outputDir := "" outputDir := ""
var explicitArgs []string
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
if !strings.HasPrefix(args[i], "-") { if !strings.HasPrefix(args[i], "-") {
if !inPkg && packageNames == nil { if !inPkg && packageNames == nil {
@ -114,6 +115,12 @@ func testFlags(args []string) (packageNames, passToTest []string) {
// make non-nil: we have seen the empty package list // make non-nil: we have seen the empty package list
packageNames = []string{} packageNames = []string{}
} }
if args[i] == "-args" || args[i] == "--args" {
// -args or --args signals that everything that follows
// should be passed to the test.
explicitArgs = args[i+1:]
break
}
passToTest = append(passToTest, args[i]) passToTest = append(passToTest, args[i])
continue continue
} }
@ -191,6 +198,8 @@ func testFlags(args []string) (packageNames, passToTest []string) {
} }
passToTest = append(passToTest, "-test.outputdir", dir) passToTest = append(passToTest, "-test.outputdir", dir)
} }
passToTest = append(passToTest, explicitArgs...)
return return
} }