Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: The go test command cannot parse custom args with flag.Parse() #39206

Closed
the1mills opened this issue May 21, 2020 · 6 comments
Closed

Bug: The go test command cannot parse custom args with flag.Parse() #39206

the1mills opened this issue May 21, 2020 · 6 comments

Comments

@the1mills
Copy link

@the1mills the1mills commented May 21, 2020

What version of Go are you using (go version)?

go version go1.14 darwin/amd64

Does this issue reproduce with the latest release?

yes 1.14

What operating system and processor architecture are you using (go env)?

go env Output
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/alex/Library/Caches/go-build"
GOENV="/Users/alex/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/alex/go"
GOPRIVATE=""
GOPROXY="direct"
GOROOT="/usr/local/Cellar/go/1.14/libexec"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.14/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/alex/go/src/github.com/channelmeter/cp-go-api/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/qh/l8tr6tfd3gv7fmdg0b5z0p340000gn/T/go-build971392475=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I ran:

go test -v github.com/cm/some-pkg -- --env=local

What did you expect to see?

I expected flag.Parse() to capture the flag

What did you see instead?

the --env flag is not captured, even though it appears in the args list when I use:

  fmt.Println(len(os.Args), os.Args)

I see:

[/var/folders/qh/l8tr6tfd3gv7fmdg0b5z0p340000gn/T/go-build589736069/b001/roles.test -test.timeout=10m0s -test.v=true  -- --env=local]

I put the Q on SO first:
https://stackoverflow.com/questions/61944527/how-to-pass-custom-flags-to-go-test?noredirect=1#comment109560255_61944527

@paulgriffiths
Copy link

@paulgriffiths paulgriffiths commented May 22, 2020

This is not a bug. From the documentation for package flag:

Flag parsing stops just before the first non-flag argument ("-" is a non-flag argument) or after the terminator "--".

and your --env flag appears after the terminator "--", so it's correctly not being parsed.

@as
Copy link
Contributor

@as as commented May 22, 2020

This is a common idiom you will see in many command line tools, not just Go.

-- terminates the argument parser explicitly, because sometimes you have arguments, such as file names, that start with - which you want to capture as a value instead of a flag.

@ORESoftware
Copy link

@ORESoftware ORESoftware commented May 22, 2020

well then you know what i am trying to do. so what is the solution?

@pschultz
Copy link

@pschultz pschultz commented May 22, 2020

Flags in tests are really no different than in any other program, except that you don't get to call flag.Parse() yourself:

package main

import (
	"flag"
	"log"
	"os"
	"testing"
)

var x = flag.Bool("env", false, "")

// run with `go test --env`
func TestFlags(t *testing.T) {
	log.Println(os.Args)     // /tmp/go-build197321626/b001/tmp.lW3vriEIbp.test -test.timeout=10m0s --env
	log.Println(flag.Args()) // []
	log.Println(*x)          // true
}

To treat arguments as flags create a dedicated FlagSet:

// run with `go test -- --env`
func TestArgs(t *testing.T) {
	fs := flag.NewFlagSet("my-test", flag.ContinueOnError)
	y := fs.Bool("env", false, "")

	log.Println(os.Args)     // [/tmp/go-build483180072/b001/tmp.lW3vriEIbp.test -test.timeout=10m0s -- --env]
	log.Println(flag.Args()) // [--env]

	if err := fs.Parse(flag.Args()); err != nil {
		t.Fatal(err)
	}

	log.Println(*y) // true
}
@mvdan
Copy link
Member

@mvdan mvdan commented May 22, 2020

The docs for the interaction between testing and flag.Parse were a bit ambiguous, so I made them clearer a couple of weeks ago in #38952.

If anything is still confusing, please suggest doc improvements. Aside from that, I agree that the current behavior seems to be correct.

@gopherbot
Copy link

@gopherbot gopherbot commented Jun 22, 2020

Timed out in state WaitingForInfo. Closing.

(I am just a bot, though. Please speak up if this is a mistake or you have the requested information.)

@gopherbot gopherbot closed this Jun 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
8 participants
You can’t perform that action at this time.