-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Description
The new introduced synctest package with go 1.25 is pretty handy for asynchronous testing. The problem is that the testify suite is not yet ready to make proper use of it. To use synctest all timer, channels, ... need to be created inside the bubble (inside synctest.Test). If you want to reuse channels or timers of a suite, this is currently not possible, because the SetupTest function for example is executed before we can call synctest.Test inside a suite test function.
Example:
package sync_test
import (
"fmt"
"testing"
"testing/synctest"
"time"
"github.com/stretchr/testify/suite"
)
func TestSync(t *testing.T) {
suite.Run(t, new(TestSuiteSync))
}
type TestSuiteSync struct {
suite.Suite
ticker *time.Ticker
}
func (s *TestSuiteSync) SetupTest() {
s.ticker = time.NewTicker(time.Second)
}
func (s *TestSuiteSync) TestWithSyncTestDoesNotWork() {
synctest.Test(s.T(), func(t *testing.T) {
<-s.ticker.C
})
}
func (s *TestSuiteSync) TestWithSyncTestDoesWork() {
synctest.Test(s.T(), func(t *testing.T) {
s.SetupTest() // call setup again to create ticker in bubble
<-s.ticker.C
})
}Output:
Proposed solution
My solution for now would be to introduce a new pattern to discover which tests in a suite shall be run with synctest.Test instead t.Run. Currently every method of the suite that starts with Test* is considerd as a synchronous test and will be run with t.Run. What if we introduce SyncTest* as prefix for suite methods that will be run with synctest.Test? I would not use TestSync* because this could break already written tests of testify users.
For subtest a new method s.RunSync could be provided to run subtests in a bubble. This should only be allowed in synchronous test methods (Test*), because it is not allowed to run a synctest bubble in another synctest bubble.
Open Problems to solve:
- How to make sure
SetupSuiteis also called inside the bubble or how to avoid setup channels and timers insideSetupSuite
Example:
package sync_test
import (
"testing"
"time"
"github.com/stretchr/testify/suite"
)
func TestTicker(t *testing.T) {
suite.Run(t, new(TestSuiteTicker))
}
type TestSuiteTicker struct {
suite.Suite
ticker *time.Ticker
}
func (s *TestSuiteTicker) SetupTest() {
s.ticker = time.NewTicker(time.Second)
}
// t.Run()
// s.SetupTest()
func (s *TestSuiteTicker) TestRealClock() {
<-s.ticker.C
// takes 1s
}
// synctest.Test()
// s.SetupTest()
func (s *TestSuiteTicker) SyncTestFakeClock() {
<-s.ticker.C
// takes ~0s
}Use case
Suites where you want to test synchronous and asynchronous.