go test fails with "can't load package build constraints exclude all Go files" - go

When I run this command
go test -tags integration $(go list ./... | grep -v /vendor/)
go fails with this for some packages that has all tests marked with // +build !integration
can't load package: build constraints exclude all Go files
Is there a way I can make go test ignore those packages in this case, instead of failing? Thanks

You will only get that error if all the files in the package are excluded by your build constraints, not just the test files. If that's what you want, just add a single package file with no code and the package will still be able to be loaded. For example, many packages put their package level docs in a separate file, which you could use to always have a valid package:
// Package foo does foo
package foo

For whatever it's worth : I was seeing similar errors while building my code. In my case, my main file had // +build go1.13 at the top of it and I was trying to get the file built using go1.12.x. Removing +build go1.13 fixed the issue.

The package you are importing might contain some source files with a conditional complication flag, which is a directive you may find at the top of the files like:
//+build linux darwin windows
package main
import "fmt"
func main() {
fmt.Println("hello")
}
The +build directive followed by one or multiple platforms indicates where this source code is supposed to be compiled on.
Therefore, you can simply try removing this directive to resolve the failure.
It worked for me.

Following on from snowfox's answer, if you can't remove the directive (becuase it was likely put there for a reason), you can still run the test by using the tag that was applied to that file (more info here).
If your file start looks like this:
//go:build bar
package foo
Then you can run the test by running go test ./foo_test.go --tags=bar

Related

How to test library functions in Golang

I'm learning Go so I'm writing some basic utils and libraries for fun that I can reuse in other modules.
When importing them inside another module (using go get for example), I can use them just fine.
As I understand, Go will look for a package main and a main function to know the entrypoint when trying to run a go app/module.
The thing is that the libraries are not in "package main", not in main.go and have no main function, so how am I supposed to use the cli and use go run . to test the behavior of my function?
Do I absolutely need to create another module with a main.go file inside a package main?
Or do I need to create a test file and use go test ?
Thank you!
Non-main packages (i.e., library packages) are not runnable.
To run the code in them, you must either run a main package that imports and runs their code, or write test functions in _test.go files to run the code. Note that test files are not just for unit tests; you can write whatever you want in them, and they can often be easier than creating a new main package for testing.
Modern IDEs now will allow you to easily run individual tests in debugging mode, so you can step through your code and see if it's working how you expect. If you prefer print debugging and doing everything from the command-line, you can still run an individual test and see the print output like this:
// something_test.go
package mylibrary
func TestSomeFunction(t *testing.T) {
SomeFunction()
}
go test mylibrary -v -run TestSomeFunction
go test is the preferred way to test Go code.
If you do not want to use go test for some reason, then use build constraints and the go run command to execute a main program from the same directory as your package.
Here's an example program with a build constraint. Place the file in the same directory as the package source files. The comment //go:build ignore is a build constraint that excludes the file from the package sources.
//go:build ignore
package main
import (
"your/package/import/path" // <-- modify to your path
"fmt"
)
func main() {
// do something with your package here.
fmt.Println("example")
}
Assuming that the above file is named program.go, run the program from the package directory with the command:
go run program.go
The go run command is OK for running toy or test programs like this. Prefer the go build command for anything else.

go test can not load package with command: go test file1_test.go file2.go

I am writing units test. I put all of the test files in other directory. Let's say the folder mypack.
There two files in the folder fun1_test.go and base.go.
The base.go has same common basic functions which are called by fun1_test.go. The base.go looks like:
package mypack_test
import (
.....
)
func Base1() {
// some code
}
The func1_test.go has functions which test func1. The func1_test.go looks like:
package mypack_test
import (
.....
)
func TestFunc1() {
// some code
Base1()
// some code
}
When I use command
go test func1_test.go base.go
There will be an error:
can't load package: package main: found packages mypack (func1_test.go) and mypack_test (base.go)
Can any one tell me why this happend. I know If the change the file base.go to base_test.go. The command will work ok. But I want to know why.
UPDATE:
I notice some of you guys misunderstanding the problem. The problem is not about if the two file need the other packages or one can call one.
The problem is that: If you have two file with same package, the package name looks like xxx_test. But the two files' name are yyy_test.go and zzz.go. When using go test yyy_test.go zzz.go command, there will be an error said they two file not in same packages.
The error are: can't load package: package main: found packages xxx (yyy_test.go) and xxx_test (zzz.go)
You should follow go's best practices.
That is:
Package names should contain only letters with no underscores.
Test file should be name of original file + test like: base.go - base_test.go.
Run test by going to packages directory and running go test.
If you make those changes, your tests should run without any problems.
If you checkout the go help test command there is this:
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.
What is happening is that your file yyy_test.go is recognised as a test file because of its _test.go ending. The package defined in that file package xxx_test is considered to be the test version of the xxx package.
See this stack answer for desc: https://stackoverflow.com/a/31443271/6376471
Then, along comes zzz.go which is not recognised as a test file, because it's missing the _test.go suffix, it has a packge xxx_test which is not considered to be a test package.
This means that essentially you are defining the packages xxx_test from zzz.go and xxx from yyy_test.go, even though yyy_test.go actually defines xxx_test, but it's in a test file so handled differently.
Solutions:
Identify zzz.go as a test file by making it zzz_test.go.
Set zzz.go to have the non test package name package xxx instead of package xxx_test.

golang reference struct in same package in another file

How to reference MyStruct in another file in the same package or folder?
Currently I get undefined: MyStruct when go build lib/file_2.go. I can run go install with no error, should I just ignore the build error?
These are my files:
lib/file_1.go
...
package lib
...
type MyStruct struct{
}
....
lib/file_2.go
...
package lib
...
{
m MyStruct
}
....
Thanks
This command works for me
go run *.go
Actually this will compile all go file and run your main function. So this works well
You're asking the go tool to compile lib/file_1.go, you never mention lib/file_2.go so how is it supposed to know it should compile it?
From go help build:
Build compiles the packages named by the import paths,
along with their dependencies, but it does not install the results.
If the arguments are a list of .go files, build treats them as a list
of source files specifying a single package.
You should be able to use MyStruct directly, since it is in the same package as its definition.
If you have any issue, sometimes it can help (for an IDE like SublimeText + GoSublime, for instance) to do a go install before creating lib/file_2.go.
That way, lib/file_1.go is compiled and present in GOPATH/pkg, with lib/file_1.go definitions visible for lib/file_2.go to use during its compilation.
According to https://golang.org/doc/tutorial/getting-started, you should run:
go run .
You have to compile the multiple files using the build command first.
go build
Now you can see a build file got generated with the given name or the folder name in case of default. Then run the binary.
./binary_file_name

How to export data from a test package and use them in another test package in go

I'm creating some vars in B_test.go and I want to use those same vars in A_test.go. Can this be done in Go? I think the question boils down to whether I can export functions from B_test.go during go test only.
Example:
In package A_test.go
package A
var from_B = B.ExportedVars()
In package B_test.go
package B
ExportedVars() []int {
return []int{0, 1)
}
Running go test gives
undefined B.ExportedVars
Putting ExportedVars() in B.go instead of B_test.go solves the problem but this is not what I want. I want it to live in the test file.
Packages cannot see exported symbols from other package's test files, because the go tools do not build those files into the installed package. One option you do have is to use build constraints.
Create a file or files that contain everything you want to export for whatever reason, without using the _test.go suffix. Then mark them for build only when using your chosen tag.
// +build export
package normal
var ExportedName = somethingInternal
When testing a package dependent on this ExportedName in package normal, you will need to add the -tags export flag to the test run.
This is also useful for various other reasons, like having a -tags debug build, which can add extra functionality such as importing net/http/pprof or expvar

go test can't find function in a same package

The directory structure is :
src
src/pkg
src/pkg/t1.go
src/pkg/t1_test.go
t1.go
package pkg
import (
"fmt"
)
func SayHI(){
fmt.Println("this is t1")
}
t1_test.go
package pkg
import (
"testing"
)
func TestXYZ(t *testing.T) {
SayHI()
}
Invoke go test from command line at dir src/pkg
go test t1_test.go
error:
./t1_test.go:8: undefined: SayHI
FAIL command-line-arguments [build failed]
but the function is there
thanks for any hints
It is working as intended.
jnml#fsc-r630:~/src/pkg$ go help test
usage: go test [-c] [-i] [build flags] [packages] [flags for test binary]
'Go test' automates testing the packages named by the import paths.
It prints a summary of the test results in the format:
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
followed by detailed output for each failed package.
'Go test' recompiles each package along with any files with names matching
the file pattern "*_test.go". These additional files can contain test functions,
benchmark functions, and example functions. See 'go help testfunc' for more.
By default, go test needs no arguments. It compiles and tests the package
with source in the current directory, including tests, and runs the tests.
The package is built in a temporary directory so it does not interfere with the
non-test installation.
In addition to the build flags, the flags handled by 'go test' itself are:
-c Compile the test binary to pkg.test but do not run it.
-i
Install packages that are dependencies of the test.
Do not run the test.
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.
For more about build flags, see 'go help build'.
For more about specifying packages, see 'go help packages'.
See also: go build, go vet.
jnml#fsc-r630:~/src/pkg$
In other words:
go test is okay.
go test pkg (assuming $GOPATH is ~ and the package is in ~/src/pkg) is okay.
go test whatever_test.go is not okay as that is not supported as documented above.
To select which tests to run use the -run <regular_expression> flag (where the <regular_expression> is interpreted as having wildcards on either end, like .*<regular_expression>.*). For example
$ go test -run Say # from within the package's directory
or
$ go test -run Say my/package/import/path # from anywhere
This is somewhat strange in Golang. To be honest it took me some time to figure a way out.
A simple work-around is to include them in the command, eg:
go test src/pkg/t1.go src/pkg/t1_test.go
IMHO, The best way is to keep it clean. So avoid having more than 1 file as dependency per test file. If you are using +1 file as dependency, consider creating a black-box test with a _test package and do not make use of any lowerCase internal vars.
This will avoid you having to deal with complicated dependencies on your day to day testing.
Run
go test ./...
This will find all the tests in all test files. To run individual tests, specify the dependencies like here.
I came across this Stackoverflow question after encountering the exact same issue myself: specifically, attempting to run go test and then seeing a build failure indicating that the function in question isn't defined. I see that this question is somewhat old now (asked 8 years ago) but in my case the issue was that I was attempting to write code in Go 1.16 that seems to now assume the presence/use of modules. See this page for a starting reference on modules and easy follow-along example.
All I had to do in my case was run go mod init [module name] and after that I could run go test without any issues.
Hopefully this is of some value to users coming to this page after using a more modern (1.16+) version of Go.

Resources