Skip to content

Commit 541ca69

Browse files
authored
refactor(test): decouple examples from test infrastructure (#2)
* refactor(test): move testutil out of examples into internal/testsupport examples 不再被测试 import;保留 offline/live build-tag 切分;14 个测试 repoint。 Task: 1789906940 * test(forward): name identity in execution e2e
1 parent 09cb2c6 commit 541ca69

22 files changed

Lines changed: 96 additions & 147 deletions

‎examples/testutil/live.go‎

Lines changed: 0 additions & 34 deletions
This file was deleted.

‎examples/testutil/testutil.go‎

Lines changed: 0 additions & 34 deletions
This file was deleted.

‎forward/batch_execution_live_test.go‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ import (
1313
"testing"
1414

1515
"github.com/QoderAI/qoder-cloud-agents-sdk-go/convention/option"
16-
"github.com/QoderAI/qoder-cloud-agents-sdk-go/examples/testutil"
1716
"github.com/QoderAI/qoder-cloud-agents-sdk-go/forward"
17+
"github.com/QoderAI/qoder-cloud-agents-sdk-go/internal/testsupport"
1818
)
1919

2020
func TestForwardBatchE2ELive(t *testing.T) {
21-
testutil.RequireE2E(t, "FORWARD")
21+
testsupport.RequireE2E(t, "FORWARD")
2222
s := newLiveSuite(t, "WRITE", "EXECUTION")
23-
ctx, cancel := context.WithTimeout(context.Background(), testutil.ExecutionTimeout(t))
23+
ctx, cancel := context.WithTimeout(context.Background(), testsupport.ExecutionTimeout(t))
2424
defer cancel()
2525
identity := s.identity(t)
2626
template := s.template(t, s.environment(t).ID)
27-
marker := testutil.Marker(t)
27+
marker := testsupport.Marker(t)
2828
customID := liveName("task")
2929
line, err := json.Marshal(map[string]any{"custom_id": customID, "template_id": template.ID, "identity_id": identity.ID, "body": map[string]any{"input": "Reply with exactly " + marker}})
3030
liveCheck(t, err)
@@ -44,7 +44,7 @@ func TestForwardBatchE2ELive(t *testing.T) {
4444
if batchTerminal(batch.Status) {
4545
break
4646
}
47-
if err = testutil.PollPause(ctx); err != nil {
47+
if err = testsupport.PollPause(ctx); err != nil {
4848
t.Fatalf("batch=%s status=%s (execution depends on the server's batch window): %v", batchID, batch.Status, err)
4949
}
5050
}
@@ -132,7 +132,7 @@ func (s *liveSuite) finishBatch(ctx context.Context, id, customID, identityID, t
132132
if batchTerminal(current.Status) {
133133
break
134134
}
135-
if err = testutil.PollPause(ctx); err != nil {
135+
if err = testsupport.PollPause(ctx); err != nil {
136136
return fmt.Errorf("batch=%s remains %s: %w", id, current.Status, err)
137137
}
138138
}
@@ -144,7 +144,7 @@ func (s *liveSuite) finishBatch(ctx context.Context, id, customID, identityID, t
144144
}
145145
rows, err := s.batchOutput(ctx, id)
146146
if err != nil {
147-
return &testutil.CleanupFailure{Err: err}
147+
return &testsupport.CleanupFailure{Err: err}
148148
}
149149
if len(rows) != 1 || rows[0].CustomID != customID || rows[0].IdentityID != identityID || rows[0].TemplateID != templateID {
150150
return fmt.Errorf("batch=%s cleanup output does not match the test input", id)

‎forward/cleanup_live_test.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package forward_test
55
import (
66
"context"
77
"encoding/json"
8-
"github.com/QoderAI/qoder-cloud-agents-sdk-go/examples/testutil"
8+
"github.com/QoderAI/qoder-cloud-agents-sdk-go/internal/testsupport"
99
"io"
1010
"net/http"
1111
"net/http/httptest"
@@ -128,7 +128,7 @@ func TestBatchMissingOutputCleanupOffline(t *testing.T) {
128128
return reply(r, 200, `{"id":"batch","status":"cancelled","output_file_id":"internal","request_counts":{"total":1}}`), nil
129129
})}
130130
err := s.finishBatch(context.Background(), "batch", "task", "identity", "template")
131-
if err == nil || testutil.ResourceAlreadyGone(err) {
131+
if err == nil || testsupport.ResourceAlreadyGone(err) {
132132
t.Fatalf("missing output silently ignored: %v", err)
133133
}
134134
}

‎forward/execution_live_test.go‎

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import (
1212

1313
"github.com/QoderAI/qoder-cloud-agents-sdk-go/convention"
1414
"github.com/QoderAI/qoder-cloud-agents-sdk-go/convention/option"
15-
"github.com/QoderAI/qoder-cloud-agents-sdk-go/examples/testutil"
1615
"github.com/QoderAI/qoder-cloud-agents-sdk-go/forward"
16+
"github.com/QoderAI/qoder-cloud-agents-sdk-go/internal/testsupport"
1717
)
1818

1919
func (s *liveSuite) waitTurn(t *testing.T, sessionID, after string, expected []string, tool, streaming bool) {
2020
t.Helper()
21-
ctx, cancel := context.WithTimeout(context.Background(), testutil.ExecutionTimeout(t))
21+
ctx, cancel := context.WithTimeout(context.Background(), testsupport.ExecutionTimeout(t))
2222
defer cancel()
23-
result := testutil.TurnResult{LastID: after}
23+
result := testsupport.TurnResult{LastID: after}
2424
observe := func(raw string) bool {
2525
t.Helper()
2626
if err := result.Observe(raw); err != nil {
@@ -29,7 +29,7 @@ func (s *liveSuite) waitTurn(t *testing.T, sessionID, after string, expected []s
2929
return result.Complete
3030
}
3131
if streaming {
32-
stream := s.client.Sessions.Events.StreamEvents(ctx, sessionID, forward.SessionEventStreamParams{LastEventID: forward.String(after), IncludeToolCalls: forward.Bool(true)}, option.WithRequestTimeout(testutil.ExecutionTimeout(t)))
32+
stream := s.client.Sessions.Events.StreamEvents(ctx, sessionID, forward.SessionEventStreamParams{LastEventID: forward.String(after), IncludeToolCalls: forward.Bool(true)}, option.WithRequestTimeout(testsupport.ExecutionTimeout(t)))
3333
defer stream.Close()
3434
for stream.Next() {
3535
if observe(stream.Current().RawJSON()) {
@@ -54,7 +54,7 @@ func (s *liveSuite) waitTurn(t *testing.T, sessionID, after string, expected []s
5454
if result.Complete {
5555
break
5656
}
57-
liveCheck(t, testutil.PollPause(ctx))
57+
liveCheck(t, testsupport.PollPause(ctx))
5858
}
5959
}
6060
if err := result.Verify(expected, tool); err != nil {
@@ -93,7 +93,7 @@ func (s *liveSuite) finishSession(ctx context.Context, id string) error {
9393
if session.Status == "idle" || session.Status == "terminated" {
9494
break
9595
}
96-
if err = testutil.PollPause(ctx); err != nil {
96+
if err = testsupport.PollPause(ctx); err != nil {
9797
return err
9898
}
9999
}
@@ -102,12 +102,15 @@ func (s *liveSuite) finishSession(ctx context.Context, id string) error {
102102
return err
103103
}
104104
func TestForwardExecutionE2ELive(t *testing.T) {
105-
testutil.RequireE2E(t, "FORWARD")
105+
testsupport.RequireE2E(t, "FORWARD")
106106
s := newLiveSuite(t, "WRITE", "EXECUTION")
107107
ctx := s.context(t)
108108
env := s.environment(t)
109-
identity := s.identity(t)
110-
fileToken, envToken, skillToken, memoryToken := testutil.Marker(t), testutil.Marker(t), testutil.Marker(t), testutil.Marker(t)
109+
identityName := liveName("identity")
110+
identity, err := s.client.Identities.New(ctx, forward.IdentityNewParams{ExternalID: identityName, Name: forward.String(identityName), Metadata: map[string]any{"suite": "sdk-live"}})
111+
liveCheck(t, err)
112+
s.cleanup(t, "identity", func(ctx context.Context) error { _, err := s.client.Identities.Delete(ctx, identity.ID); return err })
113+
fileToken, envToken, skillToken, memoryToken := testsupport.Marker(t), testsupport.Marker(t), testsupport.Marker(t), testsupport.Marker(t)
111114
file := s.file(t, "sdk-e2e.txt", "session_resource", fileToken)
112115
skillName := liveName("proof")
113116
skill, err := s.client.Skills.New(ctx, forward.SkillNewParams{Files: []io.Reader{convention.UploadFile{Name: skillName + "/SKILL.md", Reader: strings.NewReader(fmt.Sprintf("---\nname: %s\ndescription: Provides the SDK_E2E_SKILL_TOKEN for SDK verification.\n---\nWhen asked for SDK_E2E_SKILL_TOKEN return exactly: %s\n", skillName, skillToken))}}})
@@ -136,7 +139,7 @@ func TestForwardExecutionE2ELive(t *testing.T) {
136139
liveCheck(t, err)
137140
s.cleanupSession(t, session.ID)
138141
t.Logf("model=%s identity=%s template=%s file=%s skill=%s memory_store=%s", os.Getenv("QODER_FORWARD_MODEL"), identity.ID, template.ID, file.ID, skill.ID, store.ID)
139-
echo := testutil.Marker(t)
142+
echo := testsupport.Marker(t)
140143
for _, scenario := range []struct {
141144
name, prompt string
142145
expected []string

‎forward/failure_contracts_test.go‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package forward_test
22

33
import (
4-
"github.com/QoderAI/qoder-cloud-agents-sdk-go/examples/testutil"
4+
"github.com/QoderAI/qoder-cloud-agents-sdk-go/internal/testsupport"
55
"testing"
66
)
77

88
func TestForwardFailureContracts(t *testing.T) {
9-
var endpoints []testutil.Endpoint
9+
var endpoints []testsupport.Endpoint
1010
for _, c := range contracts(t) {
11-
endpoints = append(endpoints, testutil.Endpoint{Service: c.Service, Method: c.Name})
11+
endpoints = append(endpoints, testsupport.Endpoint{Service: c.Service, Method: c.Name})
1212
}
13-
testutil.FailureContracts(t, endpoints, func(fn testutil.Transport) any { return testClient(roundTripFunc(fn)) })
13+
testsupport.FailureContracts(t, endpoints, func(fn testsupport.Transport) any { return testClient(roundTripFunc(fn)) })
1414
}

‎forward/live_helpers_live_test.go‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import (
1414

1515
"github.com/QoderAI/qoder-cloud-agents-sdk-go/convention"
1616
"github.com/QoderAI/qoder-cloud-agents-sdk-go/convention/option"
17-
"github.com/QoderAI/qoder-cloud-agents-sdk-go/examples/testutil"
1817
"github.com/QoderAI/qoder-cloud-agents-sdk-go/forward"
18+
"github.com/QoderAI/qoder-cloud-agents-sdk-go/internal/testsupport"
1919
)
2020

2121
type liveSuite struct {
@@ -43,7 +43,7 @@ func newLiveSuite(t *testing.T, gates ...string) *liveSuite {
4343
}
4444
}
4545
timeout := time.Duration(seconds) * time.Second
46-
return &liveSuite{timeout: timeout, scenarioTimeout: testutil.ExecutionTimeout(t), client: forward.NewClient(option.WithPAT(os.Getenv("QODER_FORWARD_PAT")), option.WithRequestTimeout(timeout), option.WithMaxRetries(0), testutil.RequestLog(t))}
46+
return &liveSuite{timeout: timeout, scenarioTimeout: testsupport.ExecutionTimeout(t), client: forward.NewClient(option.WithPAT(os.Getenv("QODER_FORWARD_PAT")), option.WithRequestTimeout(timeout), option.WithMaxRetries(0), testsupport.RequestLog(t))}
4747
}
4848

4949
func liveEnabled(gate string) bool {
@@ -54,7 +54,7 @@ func liveName(prefix string) string { return fmt.Sprintf("sdk-%s-%d", prefix, ti
5454
func liveCheck(t *testing.T, err error) {
5555
t.Helper()
5656
if err != nil {
57-
t.Fatal(testutil.SafeError(err))
57+
t.Fatal(testsupport.SafeError(err))
5858
}
5959
}
6060
func (s *liveSuite) context(t *testing.T) context.Context {
@@ -69,10 +69,10 @@ func (s *liveSuite) cleanup(t *testing.T, label string, fn func(context.Context)
6969
ctx, cancel := context.WithTimeout(context.Background(), s.scenarioTimeout)
7070
defer cancel()
7171
if err := fn(ctx); err != nil {
72-
if testutil.ResourceAlreadyGone(err) {
72+
if testsupport.ResourceAlreadyGone(err) {
7373
return
7474
}
75-
t.Errorf("cleanup %s: %s", label, testutil.SafeError(err))
75+
t.Errorf("cleanup %s: %s", label, testsupport.SafeError(err))
7676
}
7777
})
7878
}

‎forward/schedule_execution_live_test.go‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ package forward_test
55
import (
66
"context"
77
"fmt"
8-
"github.com/QoderAI/qoder-cloud-agents-sdk-go/examples/testutil"
98
"github.com/QoderAI/qoder-cloud-agents-sdk-go/forward"
9+
"github.com/QoderAI/qoder-cloud-agents-sdk-go/internal/testsupport"
1010
"testing"
1111
)
1212

1313
func TestForwardScheduleE2ELive(t *testing.T) {
14-
testutil.RequireE2E(t, "FORWARD")
14+
testsupport.RequireE2E(t, "FORWARD")
1515
s := newLiveSuite(t, "WRITE", "EXECUTION")
16-
ctx, cancel := context.WithTimeout(context.Background(), testutil.ExecutionTimeout(t))
16+
ctx, cancel := context.WithTimeout(context.Background(), testsupport.ExecutionTimeout(t))
1717
defer cancel()
1818
env := s.environment(t)
1919
identity := s.identity(t)
2020
template := s.template(t, env.ID)
21-
marker := testutil.Marker(t)
21+
marker := testsupport.Marker(t)
2222
schedule, err := s.client.Schedules.New(ctx, forward.ScheduleNewParams{IdentityID: identity.ID, TemplateID: template.ID, EnvironmentID: env.ID, Name: liveName("schedule-e2e"), InitialEvents: []map[string]any{{"type": "user.message", "content": "Reply with exactly " + marker}}, TriggerPolicy: map[string]any{"type": "manual"}, Execution: map[string]any{"max_attempts": 1, "max_concurrent_runs": 1}})
2323
liveCheck(t, err)
2424
s.cleanup(t, "schedule "+schedule.ID, func(ctx context.Context) error {
@@ -43,7 +43,7 @@ func TestForwardScheduleE2ELive(t *testing.T) {
4343
if run.Status == "failed" || run.Status == "skipped" {
4444
t.Fatalf("schedule run=%s status=%s", runID, run.Status)
4545
}
46-
if err = testutil.PollPause(ctx); err != nil {
46+
if err = testsupport.PollPause(ctx); err != nil {
4747
t.Fatalf("schedule run=%s session=%s status=%s: %v", runID, sessionID, run.Status, err)
4848
}
4949
}
@@ -68,7 +68,7 @@ func (s *liveSuite) finishScheduleRun(ctx context.Context, runID, identityID str
6868
if run.Status == "completed" {
6969
return fmt.Errorf("completed run %s has no session", runID)
7070
}
71-
if err = testutil.PollPause(ctx); err != nil {
71+
if err = testsupport.PollPause(ctx); err != nil {
7272
return fmt.Errorf("run=%s remains %s without a session: %w", runID, run.Status, err)
7373
}
7474
}

‎forward/test_helpers_test.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import (
1616

1717
"github.com/QoderAI/qoder-cloud-agents-sdk-go/convention"
1818
"github.com/QoderAI/qoder-cloud-agents-sdk-go/convention/option"
19-
"github.com/QoderAI/qoder-cloud-agents-sdk-go/examples/testutil"
2019
"github.com/QoderAI/qoder-cloud-agents-sdk-go/forward"
20+
"github.com/QoderAI/qoder-cloud-agents-sdk-go/internal/testsupport"
2121
)
2222

2323
const pathSegment = "segment /?%#"
@@ -338,7 +338,7 @@ func checkDecoded(t *testing.T, result any) {
338338
}
339339
func checkFields(t *testing.T, v reflect.Value, path string) {
340340
t.Helper()
341-
testutil.CheckFields(t, v, path)
341+
testsupport.CheckFields(t, v, path)
342342
}
343343

344344
func jsonObject(t *testing.T, value any) map[string]any {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Package testutil contains shared assertions for the two SDK contract suites.
2-
package testutil
2+
package testsupport
33

44
import (
55
"context"

0 commit comments

Comments
 (0)