Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit01fe5e6

Browse files
johnstcnmafredri
andauthored
chore: add testutil.Eventually and friends (#3389)
This PR adds a `testutil` function aimed to replace `require.Eventually`.Before:```gorequire.Eventually(t, func() bool { ... }, testutil.WaitShort, testutil.IntervalFast)```After:```gorequire.True(t, testutil.EventuallyShort(t, func(ctx context.Context) bool { ... }))// or the full incantation if you need more controlctx, cancel := context.WithTimeout(ctx.Background(), testutil.WaitLong)require.True(t, testutil.Eventually(t, ctx, func(ctx context.Context) bool { ... }, testutil.IntervalSlow))```Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
1 parent46d64c6 commit01fe5e6

File tree

5 files changed

+150
-12
lines changed

5 files changed

+150
-12
lines changed

‎coderd/coderdtest/coderdtest.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -411,11 +411,11 @@ func AwaitTemplateVersionJob(t *testing.T, client *codersdk.Client, version uuid
411411

412412
t.Logf("waiting for template version job %s",version)
413413
vartemplateVersion codersdk.TemplateVersion
414-
require.Eventually(t,func()bool {
414+
require.True(t,testutil.EventuallyShort(t,func(ctx context.Context)bool {
415415
varerrerror
416-
templateVersion,err=client.TemplateVersion(context.Background(),version)
416+
templateVersion,err=client.TemplateVersion(ctx,version)
417417
returnassert.NoError(t,err)&&templateVersion.Job.CompletedAt!=nil
418-
},testutil.WaitShort,testutil.IntervalFast)
418+
}))
419419
returntemplateVersion
420420
}
421421

@@ -425,11 +425,10 @@ func AwaitWorkspaceBuildJob(t *testing.T, client *codersdk.Client, build uuid.UU
425425

426426
t.Logf("waiting for workspace build job %s",build)
427427
varworkspaceBuild codersdk.WorkspaceBuild
428-
require.Eventually(t,func()bool {
429-
varerrerror
430-
workspaceBuild,err=client.WorkspaceBuild(context.Background(),build)
428+
require.True(t,testutil.EventuallyShort(t,func(ctx context.Context)bool {
429+
workspaceBuild,err:=client.WorkspaceBuild(ctx,build)
431430
returnassert.NoError(t,err)&&workspaceBuild.Job.CompletedAt!=nil
432-
},testutil.WaitShort,testutil.IntervalFast)
431+
}))
433432
returnworkspaceBuild
434433
}
435434

@@ -439,21 +438,22 @@ func AwaitWorkspaceAgents(t *testing.T, client *codersdk.Client, build uuid.UUID
439438

440439
t.Logf("waiting for workspace agents (build %s)",build)
441440
varresources []codersdk.WorkspaceResource
442-
require.Eventually(t,func()bool {
441+
require.True(t,testutil.EventuallyLong(t,func(ctx context.Context)bool {
443442
varerrerror
444-
resources,err=client.WorkspaceResourcesByBuild(context.Background(),build)
443+
resources,err=client.WorkspaceResourcesByBuild(ctx,build)
445444
if!assert.NoError(t,err) {
446445
returnfalse
447446
}
448447
for_,resource:=rangeresources {
449448
for_,agent:=rangeresource.Agents {
450449
ifagent.Status!=codersdk.WorkspaceAgentConnected {
450+
t.Logf("agent %s not connected yet",agent.Name)
451451
returnfalse
452452
}
453453
}
454454
}
455455
returntrue
456-
},testutil.WaitLong,testutil.IntervalMedium)
456+
}))
457457
returnresources
458458
}
459459

‎coderd/coderdtest/coderdtest_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func TestNew(t *testing.T) {
1919
})
2020
user:=coderdtest.CreateFirstUser(t,client)
2121
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
22-
coderdtest.AwaitTemplateVersionJob(t,client,version.ID)
22+
_=coderdtest.AwaitTemplateVersionJob(t,client,version.ID)
2323
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
2424
workspace:=coderdtest.CreateWorkspace(t,client,user.OrganizationID,template.ID)
2525
coderdtest.AwaitWorkspaceBuildJob(t,client,workspace.LatestBuild.ID)

‎scripts/rules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func useStandardTimeoutsAndDelaysInTests(m dsl.Matcher) {
9191
m.Import("github.com/coder/coder/testutil")
9292

9393
m.Match(`context.WithTimeout($ctx, $duration)`).
94-
Where(m.File().Imports("testing")&&!m["duration"].Text.Matches("^testutil\\.")).
94+
Where(m.File().Imports("testing")&&!m.File().PkgPath.Matches("testutil$")&&!m["duration"].Text.Matches("^testutil\\.")).
9595
At(m["duration"]).
9696
Report("Do not use magic numbers in test timeouts and delays. Use the standard testutil.Wait* or testutil.Interval* constants instead.")
9797

‎testutil/eventually.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package testutil
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
// Eventually is like require.Eventually except it allows passing
12+
// a context into the condition. It is safe to use with `require.*`.
13+
//
14+
// If ctx times out, the test will fail, but not immediately.
15+
// It is the caller's responsibility to exit early if required.
16+
//
17+
// It is the caller's responsibility to ensure that ctx has a
18+
// deadline or timeout set. Eventually will panic if this is not
19+
// the case in order to avoid potentially waiting forever.
20+
//
21+
// condition is not run in a goroutine; use the provided
22+
// context argument for cancellation if required.
23+
funcEventually(ctx context.Context,t testing.TB,conditionfunc(context.Context)bool,tick time.Duration)bool {
24+
t.Helper()
25+
26+
if_,ok:=ctx.Deadline();!ok {
27+
panic("developer error: must set deadline or timeout on ctx")
28+
}
29+
30+
ticker:=time.NewTicker(tick)
31+
deferticker.Stop()
32+
fortick:=ticker.C; ; {
33+
select {
34+
case<-ctx.Done():
35+
assert.NoError(t,ctx.Err(),"Eventually timed out")
36+
returnfalse
37+
case<-tick:
38+
assert.NoError(t,ctx.Err(),"Eventually timed out")
39+
ifcondition(ctx) {
40+
returntrue
41+
}
42+
}
43+
}
44+
}
45+
46+
// EventuallyShort is a convenience function that runs Eventually with
47+
// IntervalFast and times out after WaitShort.
48+
funcEventuallyShort(t testing.TB,conditionfunc(context.Context)bool)bool {
49+
ctx,cancel:=context.WithTimeout(context.Background(),WaitShort)
50+
defercancel()
51+
returnEventually(ctx,t,condition,IntervalFast)
52+
}
53+
54+
// EventuallyMedium is a convenience function that runs Eventually with
55+
// IntervalMedium and times out after WaitMedium.
56+
funcEventuallyMedium(t testing.TB,conditionfunc(context.Context)bool)bool {
57+
ctx,cancel:=context.WithTimeout(context.Background(),WaitMedium)
58+
defercancel()
59+
returnEventually(ctx,t,condition,IntervalMedium)
60+
}
61+
62+
// EventuallyLong is a convenience function that runs Eventually with
63+
// IntervalSlow and times out after WaitLong.
64+
funcEventuallyLong(t testing.TB,conditionfunc(context.Context)bool)bool {
65+
ctx,cancel:=context.WithTimeout(context.Background(),WaitLong)
66+
defercancel()
67+
returnEventually(ctx,t,condition,IntervalSlow)
68+
}

‎testutil/eventually_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package testutil_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"go.uber.org/goleak"
9+
10+
"github.com/coder/coder/testutil"
11+
)
12+
13+
funcTestMain(m*testing.M) {
14+
goleak.VerifyTestMain(m)
15+
}
16+
17+
funcTestEventually(t*testing.T) {
18+
t.Parallel()
19+
t.Run("OK",func(t*testing.T) {
20+
t.Parallel()
21+
state:=0
22+
condition:=func(_ context.Context)bool {
23+
deferfunc() {
24+
state++
25+
}()
26+
returnstate>2
27+
}
28+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
29+
defercancel()
30+
testutil.Eventually(ctx,t,condition,testutil.IntervalFast)
31+
})
32+
33+
t.Run("Timeout",func(t*testing.T) {
34+
t.Parallel()
35+
condition:=func(_ context.Context)bool {
36+
returnfalse
37+
}
38+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitShort)
39+
defercancel()
40+
mockT:=new(testing.T)
41+
testutil.Eventually(ctx,mockT,condition,testutil.IntervalFast)
42+
assert.True(t,mockT.Failed())
43+
})
44+
45+
t.Run("Panic",func(t*testing.T) {
46+
t.Parallel()
47+
48+
panicky:=func() {
49+
mockT:=new(testing.T)
50+
condition:=func(_ context.Context)bool {returntrue }
51+
testutil.Eventually(context.Background(),mockT,condition,testutil.IntervalFast)
52+
}
53+
assert.Panics(t,panicky)
54+
})
55+
56+
t.Run("Short",func(t*testing.T) {
57+
t.Parallel()
58+
testutil.EventuallyShort(t,func(_ context.Context)bool {returntrue })
59+
})
60+
61+
t.Run("Medium",func(t*testing.T) {
62+
t.Parallel()
63+
testutil.EventuallyMedium(t,func(_ context.Context)bool {returntrue })
64+
})
65+
66+
t.Run("Long",func(t*testing.T) {
67+
t.Parallel()
68+
testutil.EventuallyLong(t,func(_ context.Context)bool {returntrue })
69+
})
70+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp