Skip to content

testing: add TB.Setenv() #41260

Closed
Closed
@sagikazarmark

Description

@sagikazarmark

Tests often verify behavior that rely on environment variables. Unfortunately, people often don't realize that setting environment variables in tests using os.Setenv will set those variables for the entire lifetime of the process. Things get even more complicated when tests are executed in parallel.

As a result, tests either fail when they shouldn't or worse: don't fail when they should.

In the first scenario (failing test), debugging the test probably leads people to the above conclusion, resulting in a code like this:

func TestSomething(t *testing.T) {
	os.Setenv("KEY", "VALUE")
	defer os.Unsetenv("ENV")
}

It's not necessarily bad, since it's explicit, but it doesn't handle errors and with multiple env vars it would be a lot of unnecessary copy-pasting of boilerplate code.

In the second scenario, it's quite easy to introduce and leave bugs in the code (I've just fixed one today).

I propose adding a Setenv method to testing.TB, *testing.T, and *testing.B something like this:

// Setenv sets an environment variable for the lifetime of the test.
// It also disables running this test in parallel with other tests.
// The environment variable is automatically cleaned up when the test exits.
func (t *T) Setenv(key string, value string) {
	if t.isParallel {
		panic("Setenv: test cannot be run in parallel with others")
	}
	
	t.disableParallel = true

	err := os.Setenv(key, value)
	if err != nil {
		t.Fatalf("Setenv: %v", err)
	}
	
	t.Cleanup(func() {
		os.Unsetenv(key)
	})
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions