Skip to content

Commit f3f7085

Browse files
manusaclaude
andcommitted
docs: update AGENTS.md with current testing patterns
Update testing documentation to reflect completed migration: - Add internal/test/ to project structure - Document testify/suite patterns with McpSuite base - Document snapshot testing and UPDATE_SNAPSHOTS env var - Update coding style to reference new testing approach - Remove outdated references to common_test.go and mcpContext Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c94cd66 commit f3f7085

1 file changed

Lines changed: 81 additions & 46 deletions

File tree

AGENTS.md

Lines changed: 81 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This MCP server enables AI assistants (like Claude, Gemini, Cursor, and others)
1515
- `podman/` - Podman/Docker CLI abstraction layer with interface definition and CLI implementation.
1616
- `podman-mcp-server/cmd/` - CLI command definition using Cobra framework.
1717
- `version/` - Version information management.
18+
- `internal/test/` – shared test utilities (McpSuite, mock podman helpers).
1819
- `.github/` – GitHub-related configuration (Actions workflows, Dependabot).
1920
- `npm/` – Node packages that wrap the compiled binaries for distribution through npmjs.com.
2021
- `python/` – Python package providing a script that downloads the correct platform binary from the GitHub releases page and runs it for distribution through pypi.org.
@@ -117,80 +118,114 @@ make test
117118

118119
### Testing Patterns and Guidelines
119120

120-
> **Note:** Tests are currently written with vanilla `testing` package but should be migrated to `testify/suite`
121-
> to match kubernetes-mcp-server patterns. See [Issue #68](https://github.com/manusa/podman-mcp-server/issues/68).
121+
Tests use `testify/suite` following the kubernetes-mcp-server patterns.
122122

123-
#### Target Testing Pattern (testify/suite)
123+
#### Test Suites
124124

125-
New tests should use `testify/suite` following the kubernetes-mcp-server pattern:
125+
All tests use `testify/suite` with the `test.McpSuite` base from `internal/test/`:
126126

127127
```go
128+
package mcp_test
129+
130+
import (
131+
"testing"
132+
133+
"github.com/mark3labs/mcp-go/mcp"
134+
"github.com/stretchr/testify/suite"
135+
136+
"github.com/manusa/podman-mcp-server/internal/test"
137+
)
138+
128139
type ContainerToolsSuite struct {
129-
suite.Suite
130-
// test fixtures
140+
test.McpSuite
131141
}
132142

133-
func (s *ContainerToolsSuite) SetupTest() {
134-
// setup before each test
143+
func TestContainerTools(t *testing.T) {
144+
suite.Run(t, new(ContainerToolsSuite))
135145
}
136146

137147
func (s *ContainerToolsSuite) TestContainerList() {
138-
s.Run("returns empty list when no containers", func() {
139-
// test implementation
140-
s.Equal(expected, actual)
148+
toolResult, err := s.CallTool("container_list", map[string]interface{}{})
149+
s.Run("returns OK", func() {
150+
s.NoError(err)
151+
s.False(toolResult.IsError)
141152
})
142-
s.Run("returns all containers when requested", func() {
143-
// test implementation
153+
s.Run("lists all containers", func() {
154+
s.Regexp("^podman container list", toolResult.Content[0].(mcp.TextContent).Text)
144155
})
145156
}
146-
147-
func TestContainerTools(t *testing.T) {
148-
suite.Run(t, new(ContainerToolsSuite))
149-
}
150157
```
151158

152159
Key patterns:
153-
- Use `testify/suite` for organizing tests into suites
160+
- Embed `test.McpSuite` for MCP server/client setup
161+
- Use `package mcp_test` (external test package) to avoid import cycles
154162
- Use nested subtests with `s.Run()` for related scenarios
155-
- Use `s.Equal()`, `s.True()`, `s.NoError()` for assertions
156-
- One assertion per test case when possible
163+
- Use `s.NoError()`, `s.False()`, `s.Regexp()`, `s.Contains()` for assertions
164+
- Use `s.Require().NoError()` for setup assertions that should stop the test
165+
166+
#### Test Infrastructure
167+
168+
The `internal/test/` package provides shared test utilities:
157169

158-
#### Current Testing Infrastructure
170+
- **`mcp.go`** - `McpSuite` base suite with:
171+
- `SetupTest()` / `TearDownTest()` - MCP server and client lifecycle
172+
- `CallTool(name, args)` - Call an MCP tool
173+
- `ListTools()` - List available tools
174+
- `WithPodmanOutput(lines...)` - Inject mock podman output
159175

160-
This project currently uses a mock Podman binary approach for testing:
176+
- **`podman.go`** - Mock podman binary helpers:
177+
- `WithPodmanBinary(t)` - Build fake podman and prepend to PATH
161178

162-
- The `testdata/podman/main.go` file contains a fake podman binary that:
163-
- Echoes the command line arguments it receives
164-
- Optionally reads from an `output.txt` file to provide mock responses
165-
- Tests build this fake binary and prepend its directory to PATH
166-
- This allows testing MCP tools without requiring an actual Podman installation
179+
- **`helpers.go`** - General utilities:
180+
- `Must[T](v, err)` - Panic on error helper
181+
- `ReadFile(path...)` - Read file relative to caller
182+
183+
#### Mock Podman Binary
184+
185+
The `testdata/podman/main.go` contains a fake podman binary that:
186+
- Echoes the command line arguments it receives
187+
- Optionally reads from an `output.txt` file to provide mock responses
188+
189+
This allows testing MCP tools without requiring an actual Podman installation.
167190

168191
#### Test Structure
169192

170-
Tests are organized in `pkg/mcp/` alongside the source files:
171-
- `common_test.go` - Shared test infrastructure (mock binary setup, MCP client helpers)
172-
- `mcp_test.go` - MCP server integration tests
173-
- `podman_container_test.go` - Container tool tests
174-
- `podman_image_test.go` - Image tool tests
175-
- `podman_network_test.go` - Network tool tests
176-
- `podman_volume_test.go` - Volume tool tests
193+
Tests are organized in `pkg/mcp/` with external test packages:
194+
- `mcp_test.go` - MCP server tests and snapshot testing
195+
- `podman_container_test.go` - Container tool tests (`ContainerToolsSuite`)
196+
- `podman_image_test.go` - Image tool tests (`ImageToolsSuite`)
197+
- `podman_network_test.go` - Network tool tests (`NetworkToolsSuite`)
198+
- `podman_volume_test.go` - Volume tool tests (`VolumeToolsSuite`)
177199

178-
#### Test Helpers
200+
#### Snapshot Testing
179201

180-
The `mcpContext` struct in `common_test.go` provides:
181-
- `testCase()` - Sets up test environment with mock binary and MCP client
182-
- `callTool()` - Calls an MCP tool with arguments
183-
- `withPodmanOutput()` - Injects mock output for podman commands
202+
Tool definitions are snapshot tested to detect unintended changes:
203+
204+
```go
205+
func (s *McpServerSuite) TestToolDefinitionsSnapshot() {
206+
tools, err := s.ListTools()
207+
s.Require().NoError(err)
208+
s.assertJsonSnapshot("tool_definitions.json", tools.Tools)
209+
}
210+
```
211+
212+
Snapshots are stored in `pkg/mcp/testdata/`. To update snapshots:
213+
214+
```bash
215+
make test-update-snapshots
216+
# or
217+
UPDATE_SNAPSHOTS=1 go test ./...
218+
```
184219

185220
#### Writing Tests
186221

187222
When adding tests:
188-
1. Use `testify/suite` pattern for new test files.
189-
2. Use the `testCase()` helper to set up the test environment.
190-
3. Use `withPodmanOutput()` to inject expected command output.
191-
4. Call tools using `callTool()` and verify the results.
192-
5. Test both success and error scenarios.
193-
6. Use nested subtests with `s.Run()` for related scenarios.
223+
1. Create a suite struct embedding `test.McpSuite`.
224+
2. Use `s.CallTool()` to invoke MCP tools.
225+
3. Use `s.WithPodmanOutput()` to inject expected command output.
226+
4. Use `s.Run()` for nested subtests with related scenarios.
227+
5. Use `s.Regexp("^pattern", text)` for prefix matching, `s.Regexp("pattern$", text)` for suffix.
228+
6. Test both success and error scenarios.
194229

195230
## Dependencies
196231

@@ -199,7 +234,7 @@ When introducing new modules run `make tidy` so that `go.mod` and `go.sum` remai
199234
## Coding style
200235

201236
- Go modules target Go **1.24** (see `go.mod`).
202-
- Tests are written with the standard library `testing` package.
237+
- Tests use `testify/suite` with the `test.McpSuite` base (see Testing section above).
203238
- Build and test steps are defined in the Makefile—keep them working.
204239
- Use interfaces for abstraction (see `pkg/podman/interface.go`).
205240

0 commit comments

Comments
 (0)