Golang: tests and working directory

45,177

Solution 1

You may be able to use the Caller to get the path to the current test source file, like this:

package sample

import (
    "testing"
    "runtime"
    "fmt"
)

func TestGetFilename(t *testing.T) {
    _, filename, _, _ := runtime.Caller(0)
    t.Logf("Current test filename: %s", filename)
}

Solution 2

I do not believe this is possible. I have not been able to find documentation stating this explicitly, but I believe go test always uses the package directory (containing the go source files) as the working directory.

Solution 3

As a workaround, I compiled the test and execute the test from the current directory.

go test -c && ./<mypackage>.test

Or, if you want a generic command that you can use, you can rename the test file with -o option.

go test -c -o xyz.test && ./xyz.test

Solution 4

No matter where the work directory is. It must be under your project Dir. So my solution is

wd, _ := os.Getwd()
for !strings.HasSuffix(wd, "<yourProjectDirName>") {
    wd = filepath.Dir(wd)
}

raw, err := ioutil.ReadFile(fmt.Sprintf("%s/src/conf/conf.dev.json", wd))

Your path should always start from your project Dir. Every time you read the file in a package and accessed by main.go or your another package unit test. It will always work.

Solution 5

While not really convenient, you can always pass it as a command line variable, for example :

package blah_test

import (
    "flag"
    "fmt"
    "os"
    "testing"
)

var (
    cwd_arg = flag.String("cwd", "", "set cwd")
)

func init() {
    flag.Parse()
    if *cwd_arg != "" {
        if err := os.Chdir(*cwd_arg); err != nil {
            fmt.Println("Chdir error:", err)
        }
    }
}

func TestBlah(t *testing.T) {
    t.Errorf("cwd: %+q", *cwd_arg)
}

Then run it like :

┌─ oneofone@Oa [/tmp]                                                                                             
└──➜ go test . -cwd="$PWD"
--- FAIL: TestBlah (0.00 seconds)
        blah_test.go:16: cwd: "/tmp"
Share:
45,177
Jesse Brands
Author by

Jesse Brands

Hobbyist programmer studying Computer Science. Often gets stuck on extremely silly and trivial things because he tends to rush! :-P

Updated on August 14, 2021

Comments

  • Jesse Brands
    Jesse Brands almost 3 years

    I'm writing some unit tests for my application in Go. The tests fail however because it cannot find the configuration files. Normally the binary looks for the configuration files in the working directory under the path conf/*.conf.

    I figured that browsing to the directory that has conf/ and running go test in it would solve it, but it still reports that the file system cannot find the path specified.

    How can I tell go test to use a certain directory as the working directory so that the tests may actually be executed?

  • Jesse Brands
    Jesse Brands about 10 years
    Thanks, that's very annoying but I suppose there's no way around it. I'll probably add a bug report/suggestion to the Go project to perhaps add a -w $d or --working-dir=$d parameter to go test.
  • Jesse Brands
    Jesse Brands about 10 years
    That's a good idea. I'm curious though, what command prompt is that you're using?
  • OneOfOne
    OneOfOne about 10 years
    I'm using fish, the specific function to show the prompt is @ github.com/OneOfOne/etc-fish/blob/master/functions/…
  • Yobert
    Yobert over 7 years
    Agreed, this is a very nice way to to do it. Combine with the Dir function from package "path/filepath" to build a path relative the input go file's folder.
  • Ralph
    Ralph over 7 years
    Unfortunately, this does not seem to work when the source code contains *template.Must(...) calls to compile HTML templates.
  • DivinesLight
    DivinesLight about 6 years
    This is the best answer for me! I could run my tests from the same dir where my binary usually runs from.
  • m90
    m90 almost 6 years
    This is very nice, but won't work if you have the (pretty common) pattern of using pkgname/cmd/pkgname.
  • Dr. Jan-Philip Gehrcke
    Dr. Jan-Philip Gehrcke over 3 years
    There should absolutely be some documentation here -- hopefully it's actually a guarantee :).
  • craigster0
    craigster0 over 3 years
    I had assumed that go ran the tests in the same directory as the source code being tested, but at least as of go version 1.15.5, the tests are compiled in a temporary directory under /tmp (e.g. /tmp/go-build549268541) and with a working directory of /tmp. So os.Chdir("..") will not work anymore. the answer using runtime.Caller(0) seems like the way to go.
  • Simon Kohlmeyer
    Simon Kohlmeyer almost 3 years
    Note that Caller retuns the package name if the tests are run using go test github.com/the/package. I'm trying to package a go application for nixpkgs and this is giving me some trouble.