testing: Go1.7 sub-test with t.Parallel() using data from loop out of its scope #16586
Comments
This is a common pattern in any kind of parallel loop. Nothing is specific to t.Run("parallel", func(t *testing.T) {
for _, tt := range routes {
tt := tt
t.Run(tt.url, func(t *testing.T) {
t.Parallel() // <== trying to set Parallel(), while using tt from the range loop
u, _ := url.Parse(tt.url)
if u.Path != tt.path {
t.Errorf("expected %v, got %v", tt.path, u.Path)
}
})
}
}) As Effective Go says, "It may seem odd to write |
@qeedquan nice find about But should we improve |
I think you mean @quentinmit This problem can happen with any API that takes a func pointer. t.Run is but one of many in that standard libary, should we really document all of them with "beware of calling this from a for loop"? If it's not obvious something will execute in parallel, I agree that should be documented, but given that the function is named "Parallel" I think that part is already documented pretty well. |
Sorry about the wrong mention, it came first after typing I agree with you, |
Hi there,
I was playing with go1.7's sub-tests today and I ran into a not really obvious side-effect of marking sub-test with
t.Parallel()
.This bahavior was not obvious to me from the beginning, since all of my tests still passed :) But after a while I figured there was a concurrency issue similar to this:
which is easy to solve by passing the value onto goroutine's stack:
Question
I'm trying to figure out a fix (similar to passing data onto goroutine's stack) for the above Parallel sub-test. Any suggestions?
Documentation suggestion
Imho, the
t.Parallel()
behavior should be documented better, especially in the context of sub-tests + table driven tests.The text was updated successfully, but these errors were encountered: