Skip to content

testing: clarification needed for testing.F method usage rules #73513

@Yakog-ux

Description

@Yakog-ux

Go version

go version go1.24.2 linux/amd64

Output of go env in your module/workspace:

/

What did you do?

The documentation for the testing.F type currently states:

*F methods can only be called before (*F).Fuzz. Once the test is executing the fuzz target, only (*T) methods can be used.

Thus, two requirements are:

  1. methods of the F type can only be used/called before (*F).Fuzz, and
  2. within a fuzz target, only methods of type T are allowed to be called.

In the following example, the second requirement is violated:

func FuzzFoo(f *testing.F) {
	f.Add(5)
	f.Fuzz(func(t *testing.T, a int) {
		t.Logf("%v\n", a)
		f.Skip() // fuzz target must not call any *F methods
	})
}

Since the 2. requirement is violated, the test fails (as expected) and the following is printed:

pk1/test2_test.go:18:3: fuzz target must not call any *F methods

Next, the following code violates the first requirement:

func FuzzFoo(f *testing.F) {
	f.Add(5)
	f.Fuzz(func(t *testing.T, a int) {
		t.Logf("%v\n", a)
	})
	f.Cleanup(func() {
		f.Logf("smth")
	})

	f.Logf("end")
}

However, in this case no error occurs ("smth" and "end" are printed, the test passed).

This raises confusion: is the statement in the documentation meant to be a strict requirement (i.e., calling any F method after (*F).Fuzz is forbidden, as in the case of the 2. requirement), or is it just a recommendation for correct setup before fuzzing starts?

Based on what is written, it seems like a requirement. However, based on the behavior, it seems like it is just a suggestion.

If it is merely a recommendation, perhaps the documentation could be updated to make that clearer — for example, by stating that calling methods after (*F).Fuzz may result in undefined behavior, instead of suggesting it is completely disallowed.

Additionally, documentation for the (*F).Add states the following:

This will be a no-op if called after or within the fuzz target, and args must match the arguments for the fuzz target.

So, in the type description it says that it is not allowed to be used after a fuzz target, and here it says that it is, but it is a no-op.

Also, in my opinion it should just say "This will be a no-op if called after the fuzz target" (assuming that requirement 1 is just a suggestion; not requirement). Calling inside the fuzz target violates requirement 2 and the test will fail (so it is not a no-op).

What did you see happen?

Inconsistency between documentation and behavior.

What did you expect to see?

Consistency between documentation and behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionIssues that are questions about using Go.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions