Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set particular environment variables during execution of a test suite

I want to run a unit test fxn in Go which has to do with env vars.

At some point I go (no pun intended)

    for test := range tests {
        for k, v := range test.envVars {
            os.Setenv(k, v)
        }

Is there a way to make sure that during the test execution, the variables set by the call to os.Setenv() above will be the only env vars available to the test function?

like image 921
pkaramol Avatar asked Jan 20 '26 17:01

pkaramol


1 Answers

You can use os.Environ to obtain the current environment and os.Unsetenv to unset it.

Presumably you would also need to restore those variables after the test completes, for which you could use a subtest per environment with (*testing.T).Cleanup (https://play.golang.org/p/A5HGZwWm-NS):

    for _, tc := range tests {
        t.Run(tc.name, func(t *testing.T) {
            // NOTE: do NOT call t.Parallel in this subtest or its parent,
            // or the environment WILL be corrupted.
            //
            // (However, *subtests of* t may be run in parallel.)

            prevEnv := os.Environ()
            for _, entry := range prevEnv {
                parts := strings.SplitN(entry, "=", 2)
                os.Unsetenv(parts[0])
            }
            for k, v := range tc.envVars {
                os.Setenv(k, v)
            }
            t.Cleanup(func() {
                for k := range tc.envVars {
                    os.Unsetenv(k)
                }
                for _, entry := range prevEnv {
                    parts := strings.SplitN(entry, "=", 2)
                    os.Setenv(parts[0], parts[1])
                }
            })

            …
        })
    }

Also note that Go 1.17 adds the (*testing.T).Setenv method, which cleans up the modification automatically. However, there is not yet a corresponding (*testing.T).Unsetenv.


If you want to be able to run tests in parallel, you could instead use subtests with os/exec and the -test.run flag to re-exec the particular subtest as a subprocess of the main test process, with its own distinct environment.

like image 94
bcmills Avatar answered Jan 23 '26 21:01

bcmills