-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Running Parallel Tests in Suite #187
Comments
That's true, but as it's currently structured it isn't possible to run suite tests in parallel. This is because before and after each suite test |
@eyphka do you want to make a PR to address it? :) |
Related: #52 |
Sure On Sunday, November 1, 2015, Ernesto Jiménez [email protected]
|
Reviving this issue. Presumably it should be possible to run suite tests in parallel. The problem with parallelism here is that the suite members used in tests have a shared single instance for all. Tests running in parallel could potentially access these members at the same time, causing them to "collide" with each other via these members. However, my suggestion is that testify will add a special This will of course require extra work from the test developer, to make sure Thoughts? |
I just whipped up a slightly different approach to running tests in parallel: Similar to #369, it introduces a Because a new suite is initialised before every test, it means tests can't share data on the suite struct. This is a change in behaviour, though I imagine you could change the patch to make a copy of the suite struct instead of initialising a new one (that way tests could still share data and setup/teardown code using I actually prefer the share-nothing approach though; it feels like a bad practice to modify data on the suite struct while tests are running, especially now in parallel. I can't see why tests should ever share data (outside what is set up in |
is it still the case that suite tests can't be run in parallel? |
Hi! Any updates on this? Are you planning to do work on this feature request? |
One solution: package main_test
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/ysmood/got"
)
func Test(t *testing.T) {
got.Each(t, beforeEach)
}
func beforeEach(t *testing.T) Suite {
t.Parallel()
return Suite{assert.New(t)}
}
type Suite struct { // struct that holds subtests
*assert.Assertions
}
func (s Suite) A() { // test case A
time.Sleep(time.Second)
s.Equal(1, 1)
}
func (s Suite) B() { // test case B
time.Sleep(time.Second)
s.Equal(2, 1)
} As you can see, test A is not affected:
|
@oryband can we implement it now? |
func (s *mySuiteA) TestA2() { // test case A
t := s.T()
t.Parallel()
assert.Equal(t, 3, 1)
} cache the This issue is caused by the following code snippet test := testing.InternalTest{
Name: method.Name,
F: func(t *testing.T) {
// ...
defer func() {
// ...
suite.SetT(parentT)
// ...
}()
// ...
method.Func.Call([]reflect.Value{reflect.ValueOf(suite)})
}
} ... and when run test in parallel, defer function executed from |
Well, it is not a solution because as tests grow the first place cache may cache a wrong pointer also. |
Then I'd suggest we pass the inner T if the test method meet the signature, i.e., func (s *mySuite) TestT(t *testing.T) |
being able to force parallelism for suites would be helpful for us as well, we are looking to ditch ginkgo but want to make sure we can force random execution order to find flaky tests and keep our overall suite runtime low |
any update about this long open issue? |
No. The same problem is described in the above thread. Missed. // SetupTest will run before each test in the suite.
func (s YourSuite) SetupTest() {
s.T().Parallel()
} |
Any moves on that? |
Here is a solution we've used. type E2ETestSuite struct {
suite.Suite
ts map[string]*testing.T // Map of test names > *testing.T
}
func (suite *E2ETestSuite) BeforeTest(_, testName string) {
t := suite.T()
if suite.ts == nil {
suite.ts = make(map[string]*testing.T, 1)
}
suite.ts[testName] = t
t.Parallel()
}
// T() overrides suite.Suite.T() with a way to find the proper *testing.T
// for the current test.
// This relies on `BeforeTest` storing the *testing.T pointers in a map
// before marking them parallel.
// This is a huge hack to make parallel testing work until
// https://github.com/stretchr/testify/issues/187 is fixed.
// There is still a small race:
// 1. test 1 calls SetT()
// 2. test 1 calls BeforeTest() with its own T
// 3. test 1 is marked as parallel and starts executing
// 4. test 2 calls SetT()
// 5. test 1 completes and calls SetT() to reset to the parent T
// 6. test 2 calls BeforeTest() with its parent T instead of its own
// The time between 4. & 6. is extremely low, enough that this should be really rare on our e2e tests.
func (suite *E2ETestSuite) T() *testing.T {
// Try to find in the call stack a method name that is stored in `ts` (the test method).
for i := 1; ; i++ {
pc, _, _, ok := runtime.Caller(i)
if !ok {
break
}
// Example rawFuncName:
// github.com/foo/bar/tests/e2e.(*E2ETestSuite).MyTest
rawFuncName := runtime.FuncForPC(pc).Name()
splittedFuncName := strings.Split(rawFuncName, ".")
funcName := splittedFuncName[len(splittedFuncName)-1]
t := suite.ts[funcName]
if t != nil {
return t
}
}
// Fallback to the globally stored Suite.T()
return suite.Suite.T()
} |
I've opened a PR to try to allow This is the approach suggested by @tisonkun in #187 (comment) |
any update about this long open issue? |
#1109 is the only good fix for this, but is a breaking change. It might be that a |
Any workaround in 2024 or is this still an ongoing issue? |
@Nikola-Milovic This is still broken and any fix would require a major API breaking change, so this will not be fixed in v1. I recommend anyone interested in building a |
testify/suite breaks parallel cron testing which was introduced in argoproj#2118 The breakage probably happened in argoproj#2874 testify know this stretchr/testify#187 and will not be fixing it. The fix here is inspired by @Jerska in stretchr/testify#187 (comment) It has a potential race but we won't be affected by it as all the tests take time to run. The tests are designed around running starting on a minute boundary for reliabilty, and as we add more tests without this fix it * increases overall reliability * test-to-test runtime varies, changing the start time relative to a minute boundary of a test, increasing uncertainty in how many instances of a cron will run. Tested locally by running the suite Signed-off-by: Alan Clucas <[email protected]>
When running multiple tests in a suite which have been set to
suite.t().Parallel()
, tests will pass even if they should fail.The text was updated successfully, but these errors were encountered: