Brad Peabody
Brad Peabody

Reputation: 11377

golang test temp directory

I have a simple function which parses a config file as JSON. I want to write a test which either uses some sample static config files and parses them, or creates the samples during the test and tries to parse them.

It's not entirely necessary to the question, but here is the basic code:

// config.go

// ...(package,imports)...

// Overall settings - corresponds to main.conf
type MainSettings struct {
    // stuff
}

// Load main.conf from the specified file path
func LoadMainSettings(path string) (*MainSettings, error) {

    b, err := ioutil.ReadFile(path)
    if err != nil { return nil, err }

    r := &MainSettings{}
    err = json.Unmarshal(b, r)
    if err != nil { return nil, err }

    return r, nil

}

and the test:

// config_test.go

func TestLoadMainSettings(t *testing.T) {

    // possibly generate some example config files,
    // or use static samples packaged with the source

    s, err := LoadMainSettings("conf/main.conf") // <-- what should this path be??
    if err != nil { panic(err) }

    // more sanity checking...

}

That said, my specific questions are:

(Note: I run most of my stuff on Linux for staging and production and Mac for local dev - so using /tmp/ as a temp dir for tests works for me in practice. But was wondering if there's a better way...)


EDIT: Ended up using this approach for the test:

f, err := ioutil.TempFile("", "testmainconf")
if err != nil { panic(err) }
defer syscall.Unlink(f.Name())
ioutil.WriteFile(f.Name(), []byte("{...sample config data...}"), 0644)

s, err := LoadMainSettings(f.Name())

But the other suggestion of making LoadMainSettings accept an io.Reader instead of a string is also a good idea.

Upvotes: 23

Views: 34386

Answers (5)

Mhammad Sellam
Mhammad Sellam

Reputation: 160

You can do this:

go env -w GOTMPDIR="C:\Users<user>\go\tmp"

Upvotes: 0

Megidd
Megidd

Reputation: 7952

You can do this too:

uniqueTempDir, err := os.MkdirTemp(os.TempDir(), "*-myOptionalSuffix")
if err != nil {
    return err
}

Upvotes: 0

jochen
jochen

Reputation: 3920

Since Go version 1.15 there is now T.TempDir() in the standard testing package. The docs explain it as follows:

TempDir returns a temporary directory for the test to use. The directory is automatically removed by Cleanup when the test and all its subtests complete. Each subsequent call to t.TempDir returns a unique directory; if the directory creation fails, TempDir terminates the test by calling Fatal.

Upvotes: 38

dyoo
dyoo

Reputation: 12023

Just to compare vs. what you have with ioutil.TempDir, here's what things look like with io.Reader:

// Load main.conf from the specified file path
func LoadMainSettings(src io.Reader) (*MainSettings, error) {
    b, err := ioutil.ReadAll(src)
    if err != nil { return nil, err }

    r := &MainSettings{}
    err = json.Unmarshal(b, r)
    if err != nil { return nil, err }

    return r, nil
}

Specifically, we change the argument from a path string to a src io.Reader instance, and we replace the ioutil.ReadFile with an ioutil.ReadAll.

The test case that you've written then ends up being a bit shorter precisely because we can dispense with file operations:

s, err := LoadMainSettings(strings.NewReader("{...sample config data...}"))

Upvotes: 10

Ask Bj&#248;rn Hansen
Ask Bj&#248;rn Hansen

Reputation: 6943

You could use ioutil.TempDir or TempFile from the same package.

Upvotes: 14

Related Questions