-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Closed
Labels
FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.The path to resolution is known, but the work has not been done.ProposalProposal-Accepted
Milestone
Description
This is a revive of #10655
Motivation
Consider the following code & corresponding tests:
package pkg
// build and cache regexp, reuse between clients
var re *regexp.Regexp
type Client struct {
// ...
}
func NewClient(pattern string) *Client {
if re == nil {
re = regexp.MustCompile(pattern)
}
return &Client{
// ...
}
}
func (c *Client) HasPattern(s string) error {
if !re.MatchString(s) {
return errors.New("meh, incorrect param")
}
return nil
}package pkg
func TestFoo(t *testing.T) {
s := NewClient("^foo.*")
err := s.HasPattern("foo123")
if err != nil {
t.Errorf("expected to pass")
}
}
func TestFooBar(t *testing.T) {
s := NewClient("^foobar.*")
err := s.HasPattern("foobar1123")
if err != nil {
t.Errorf("expected to pass")
}
}Those tests pass, everything looks fine, but they're order dependent. Running them in another order will fail.
To prevent such hidden and hard to debug mistakes we need to make the order of test random for each test build.
Current workarounds
- Manual ordering of tests.
- Boilerplate code to specify the order of tests.
- For table-driven tests we can use a map instead of slice, ex:
func TestSomething(t *testing.T) {
testCases := map[name]struct{
a,b int64
res int64
}{
“simple case”: {1, 2, 3},
“less simple”: {3, 3, 23},
}
// due to behaviour of map test cases will be
// in a different order for each run
// but this solution is limited and not suitable for test funcs
// aka `func TestXXX(t *testing.T)`
for name, tc := range testCases {
t.Logf(“test: %s”, name)
res := foo(tc.a, tc.b)
if res != tc.res {
t.Errorf(“want %v, got %v, res, tc.res)
}
}
}Possible solution
We need to specify a test run to execute tests with a random/desired order:
-shuffleto run tests with a random order (used random seed may or should be printed to output depending or not on a-vflag).-seed <int>to specify a user-defined seed to have an ability repeat a failed build.
Open questions
- Should we randomize order of benchmarks and examples? (looks like not)
- This makes test runs 'flaky' but this helps to reveal possible implementation caveats.
- This might not happen for 1.12 'cause proposal is submitted too late.
PS. if/when it will be accepted - will be happy to work on it.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.The path to resolution is known, but the work has not been done.ProposalProposal-Accepted