Skip to content

Commit e424676

Browse files
authored
[test-improver] Improve tests for mcptest harness (#2631)
# Test Improvements: `harness_test.go` ## File Analyzed - **Test File**: `internal/testutil/mcptest/harness_test.go` - **Package**: `internal/testutil/mcptest` - **Lines of Code**: 275 → 197 (−78 lines of boilerplate) ## Improvements Made ### 1. Better Testify Assertions Replaced all manual `if`-block error checking with idiomatic testify calls: - ✅ `require.NoError(t, err)` instead of `if err := ...; err != nil { t.Fatalf(...) }` - ✅ `require.Len(t, tools, 1)` instead of `if len(tools) != 1 { t.Errorf(...) }` - ✅ `assert.Equal(t, "test_echo", tools[0].Name)` instead of nested `if tools[0].Name != ...` - ✅ `assert.False(t, result.IsError)` instead of `if result.IsError { t.Error(...) }` - ✅ `require.True(t, ok, "Expected *sdk.TextContent")` instead of `if !ok { t.Error(...) }` - ✅ `assert.ElementsMatch(t, []string{"echo1", "echo2", "add"}, toolNames)` instead of manual map-lookup loop - ✅ Added `assert` import alongside existing `require` ### 2. Increased Coverage - ✅ **Added missing assertion on `add` tool result**: `assert.Equal(t, "8", textContent.Text)` — the original test called the add tool but never verified the return value - ✅ `require.Len` on `result.Content` before accessing `result.Content[0]`, preventing a potential index panic ### 3. Cleaner & More Stable Tests - ✅ Removed redundant `if len(x) > 0 { ... }` guards that were only needed because `t.Errorf` doesn't stop execution (now `require.Len` stops on failure) - ✅ Removed `t.Logf("✓ ...")` status messages that added noise without testing anything - ✅ Cleaner linear test flow without deeply nested conditionals - ✅ Consistent `err :=` declaration pattern across all test functions ## Why These Changes? `harness_test.go` already imported `require` from testify but performed most assertions via manual `if`-blocks with `t.Errorf`/`t.Fatalf`. This pattern lets tests continue running after a failure, leading to confusing cascaded errors (e.g., an index-out-of-bounds panic after a length mismatch). Converting to testify stops tests at the right boundary, gives clearer failure messages, and removes substantial boilerplate. The missing assertion on the `add` tool result was a genuine coverage gap — the test confirmed the tool call succeeded but never checked the computed value. --- *Generated by Test Improver Workflow* *Focuses on better patterns, increased coverage, and more stable tests* > Generated by [Test Improver](https://github.com/github/gh-aw-mcpg/actions/runs/23634910800) · [◷](https://github.com/search?q=repo%3Agithub%2Fgh-aw-mcpg+%22gh-aw-workflow-id%3A+test-improver%22&type=pullrequests) <!-- gh-aw-agentic-workflow: Test Improver, engine: copilot, model: auto, id: 23634910800, workflow_id: test-improver, run: https://github.com/github/gh-aw-mcpg/actions/runs/23634910800 --> <!-- gh-aw-workflow-id: test-improver -->
2 parents 3088ade + 91c7a12 commit e424676

1 file changed

Lines changed: 36 additions & 114 deletions

File tree

internal/testutil/mcptest/harness_test.go

Lines changed: 36 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import (
44
"context"
55
"fmt"
66
"testing"
7-
8-
"github.com/stretchr/testify/require"
97
"time"
108

119
sdk "github.com/modelcontextprotocol/go-sdk/mcp"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
1212

1313
"github.com/github/gh-aw-mcpg/internal/testutil/mcptest"
1414
)
@@ -24,9 +24,8 @@ func TestBasicServerWithOneTool(t *testing.T) {
2424
driver := mcptest.NewTestDriver()
2525
defer driver.Stop()
2626

27-
if err := driver.AddTestServer("test", config); err != nil {
28-
t.Fatalf("Failed to add test server: %v", err)
29-
}
27+
err := driver.AddTestServer("test", config)
28+
require.NoError(t, err, "Failed to add test server")
3029

3130
transport, err := driver.CreateStdioTransport("test")
3231
require.NoError(t, err, "Failed to create transport")
@@ -38,42 +37,19 @@ func TestBasicServerWithOneTool(t *testing.T) {
3837
// Validate tools
3938
tools, err := validator.ListTools()
4039
require.NoError(t, err, "Failed to list tools")
41-
42-
if len(tools) != 1 {
43-
t.Errorf("Expected 1 tool, got %d", len(tools))
44-
}
45-
46-
if len(tools) > 0 {
47-
if tools[0].Name != "test_echo" {
48-
t.Errorf("Expected tool name 'test_echo', got '%s'", tools[0].Name)
49-
}
50-
t.Logf("✓ Tool found: %s - %s", tools[0].Name, tools[0].Description)
51-
}
40+
require.Len(t, tools, 1, "Expected exactly 1 tool")
41+
assert.Equal(t, "test_echo", tools[0].Name)
5242

5343
// Test tool execution
5444
result, err := validator.CallTool("test_echo", map[string]interface{}{
5545
"message": "Hello, World!",
5646
})
5747
require.NoError(t, err, "Failed to call tool")
58-
59-
if result.IsError {
60-
t.Error("Tool returned an error")
61-
}
62-
63-
if len(result.Content) != 1 {
64-
t.Errorf("Expected 1 content item, got %d", len(result.Content))
65-
}
66-
67-
if len(result.Content) > 0 {
68-
textContent, ok := result.Content[0].(*sdk.TextContent)
69-
if !ok {
70-
t.Error("Expected TextContent")
71-
} else if textContent.Text != "Echo: Hello, World!" {
72-
t.Errorf("Expected 'Echo: Hello, World!', got '%s'", textContent.Text)
73-
} else {
74-
t.Logf("✓ Tool executed correctly: %s", textContent.Text)
75-
}
76-
}
48+
assert.False(t, result.IsError)
49+
require.Len(t, result.Content, 1, "Expected exactly 1 content item")
50+
textContent, ok := result.Content[0].(*sdk.TextContent)
51+
require.True(t, ok, "Expected *sdk.TextContent")
52+
assert.Equal(t, "Echo: Hello, World!", textContent.Text)
7753
}
7854

7955
// TestServerWithMultipleTools tests a server with multiple tools
@@ -111,9 +87,8 @@ func TestServerWithMultipleTools(t *testing.T) {
11187
driver := mcptest.NewTestDriver()
11288
defer driver.Stop()
11389

114-
if err := driver.AddTestServer("test", config); err != nil {
115-
t.Fatalf("Failed to add test server: %v", err)
116-
}
90+
err := driver.AddTestServer("test", config)
91+
require.NoError(t, err, "Failed to add test server")
11792

11893
transport, err := driver.CreateStdioTransport("test")
11994
require.NoError(t, err, "Failed to create transport")
@@ -125,44 +100,26 @@ func TestServerWithMultipleTools(t *testing.T) {
125100
// Validate: Should have 3 tools
126101
tools, err := validator.ListTools()
127102
require.NoError(t, err, "Failed to list tools")
103+
require.Len(t, tools, 3, "Expected exactly 3 tools")
128104

129-
if len(tools) != 3 {
130-
t.Errorf("Expected 3 tools, got %d", len(tools))
131-
}
132-
133-
// Test each tool
134-
toolNames := make(map[string]bool)
135-
for _, tool := range tools {
136-
toolNames[tool.Name] = true
137-
t.Logf("✓ Found tool: %s", tool.Name)
138-
}
139-
140-
expectedTools := []string{"echo1", "echo2", "add"}
141-
for _, expected := range expectedTools {
142-
if !toolNames[expected] {
143-
t.Errorf("Expected tool '%s' not found", expected)
144-
}
105+
// Verify all expected tools are present
106+
toolNames := make([]string, len(tools))
107+
for i, tool := range tools {
108+
toolNames[i] = tool.Name
145109
}
110+
assert.ElementsMatch(t, []string{"echo1", "echo2", "add"}, toolNames)
146111

147112
// Test the add tool
148113
result, err := validator.CallTool("add", map[string]interface{}{
149114
"a": 5.0,
150115
"b": 3.0,
151116
})
152117
require.NoError(t, err, "Failed to call add tool")
153-
154-
if result.IsError {
155-
t.Error("Add tool returned an error")
156-
}
157-
158-
if len(result.Content) > 0 {
159-
textContent, ok := result.Content[0].(*sdk.TextContent)
160-
if !ok {
161-
t.Error("Expected TextContent")
162-
} else {
163-
t.Logf("✓ Add tool result: %s", textContent.Text)
164-
}
165-
}
118+
assert.False(t, result.IsError)
119+
require.Len(t, result.Content, 1, "Expected exactly 1 content item")
120+
textContent, ok := result.Content[0].(*sdk.TextContent)
121+
require.True(t, ok, "Expected *sdk.TextContent")
122+
assert.Equal(t, "8", textContent.Text)
166123
}
167124

168125
// TestServerWithResources tests a server with resources
@@ -183,9 +140,8 @@ func TestServerWithResources(t *testing.T) {
183140
driver := mcptest.NewTestDriver()
184141
defer driver.Stop()
185142

186-
if err := driver.AddTestServer("test", config); err != nil {
187-
t.Fatalf("Failed to add test server: %v", err)
188-
}
143+
err := driver.AddTestServer("test", config)
144+
require.NoError(t, err, "Failed to add test server")
189145

190146
transport, err := driver.CreateStdioTransport("test")
191147
require.NoError(t, err, "Failed to create transport")
@@ -197,39 +153,15 @@ func TestServerWithResources(t *testing.T) {
197153
// Test: List resources
198154
resources, err := validator.ListResources()
199155
require.NoError(t, err, "Failed to list resources")
200-
201-
// Validate: Should have 1 resource
202-
if len(resources) != 1 {
203-
t.Errorf("Expected 1 resource, got %d", len(resources))
204-
}
205-
206-
if len(resources) > 0 {
207-
if resources[0].URI != "test://doc1" {
208-
t.Errorf("Expected URI 'test://doc1', got '%s'", resources[0].URI)
209-
}
210-
t.Logf("✓ Resource found: %s - %s", resources[0].URI, resources[0].Name)
211-
}
156+
require.Len(t, resources, 1, "Expected exactly 1 resource")
157+
assert.Equal(t, "test://doc1", resources[0].URI)
212158

213159
// Test: Read resource
214-
result, err := validator.ReadResource("test://doc1")
160+
readResult, err := validator.ReadResource("test://doc1")
215161
require.NoError(t, err, "Failed to read resource")
216-
217-
// Validate: Should have content
218-
if len(result.Contents) != 1 {
219-
t.Errorf("Expected 1 content item, got %d", len(result.Contents))
220-
}
221-
222-
if len(result.Contents) > 0 {
223-
content := result.Contents[0]
224-
if content.URI != "test://doc1" {
225-
t.Errorf("Expected URI 'test://doc1', got '%s'", content.URI)
226-
}
227-
if content.Text != "This is test content" {
228-
t.Errorf("Expected 'This is test content', got '%s'", content.Text)
229-
} else {
230-
t.Logf("✓ Resource read correctly: %s", content.Text)
231-
}
232-
}
162+
require.Len(t, readResult.Contents, 1, "Expected exactly 1 content item")
163+
assert.Equal(t, "test://doc1", readResult.Contents[0].URI)
164+
assert.Equal(t, "This is test content", readResult.Contents[0].Text)
233165
}
234166

235167
// TestServerInfo validates server metadata
@@ -247,9 +179,8 @@ func TestServerInfo(t *testing.T) {
247179
driver := mcptest.NewTestDriver()
248180
defer driver.Stop()
249181

250-
if err := driver.AddTestServer("test", config); err != nil {
251-
t.Fatalf("Failed to add test server: %v", err)
252-
}
182+
err := driver.AddTestServer("test", config)
183+
require.NoError(t, err, "Failed to add test server")
253184

254185
transport, err := driver.CreateStdioTransport("test")
255186
require.NoError(t, err, "Failed to create transport")
@@ -261,15 +192,6 @@ func TestServerInfo(t *testing.T) {
261192
// Test: Get server info
262193
serverInfo := validator.GetServerInfo()
263194
require.NotNil(t, serverInfo, "Server info is nil")
264-
265-
// Validate: Server name and version
266-
if serverInfo.Name != "custom-test-server" {
267-
t.Errorf("Expected name 'custom-test-server', got '%s'", serverInfo.Name)
268-
}
269-
270-
if serverInfo.Version != "2.5.0" {
271-
t.Errorf("Expected version '2.5.0', got '%s'", serverInfo.Version)
272-
}
273-
274-
t.Logf("✓ Server info validated: %s v%s", serverInfo.Name, serverInfo.Version)
195+
assert.Equal(t, "custom-test-server", serverInfo.Name)
196+
assert.Equal(t, "2.5.0", serverInfo.Version)
275197
}

0 commit comments

Comments
 (0)