Documentation
¶
Overview ¶
Package testing provides utilities for testing trading agents
Package testing provides utilities for testing trading agents
Index ¶
- func AddMockMCPServer(config *agents.AgentConfig, serverName, url string)
- func GetTestMetricsPort(t *testing.T) int
- func TestAgentConfig(name, agentType string) *agents.AgentConfig
- type AgentTestHelper
- func (h *AgentTestHelper) AddCleanup(fn func())
- func (h *AgentTestHelper) AssertMCPCallArguments(server *MockMCPServer, toolName string, expectedArgs map[string]interface{})
- func (h *AgentTestHelper) AssertMCPCallMade(server *MockMCPServer, toolName string, expectedCount int)
- func (h *AgentTestHelper) Cleanup()
- func (h *AgentTestHelper) Context() context.Context
- func (h *AgentTestHelper) CreateMockMarketDataServer() *MockMCPServer
- func (h *AgentTestHelper) CreateMockOrderExecutorServer() *MockMCPServer
- func (h *AgentTestHelper) CreateMockTechnicalIndicatorsServer() *MockMCPServer
- func (h *AgentTestHelper) CreateTestAgent(name, agentType string, metricsPort int) *agents.BaseAgent
- func (h *AgentTestHelper) Logger() zerolog.Logger
- func (h *AgentTestHelper) SimulateAgentStep(agent *agents.BaseAgent) error
- func (h *AgentTestHelper) WaitForCondition(condition func() bool, timeout time.Duration, message string) bool
- type CommonTools
- type Decision
- type DecisionPolicy
- type MarketDataFixtures
- type MockMCPServer
- func (m *MockMCPServer) CallTool(ctx context.Context, params *mcp.CallToolParams) (*mcp.CallToolResult, error)
- func (m *MockMCPServer) GetCallCount(toolName string) int
- func (m *MockMCPServer) GetCalls() []ToolCall
- func (m *MockMCPServer) GetLastCall(toolName string) *ToolCall
- func (m *MockMCPServer) GetName() string
- func (m *MockMCPServer) GetVersion() string
- func (m *MockMCPServer) ListTools(ctx context.Context, params *mcp.ListToolsParams) (*mcp.ListToolsResult, error)
- func (m *MockMCPServer) RegisterTool(tool *mcp.Tool, handler ToolHandler)
- func (m *MockMCPServer) Reset()
- type MockOrchestrator
- func (m *MockOrchestrator) GetDecisions() []Decision
- func (m *MockOrchestrator) GetLastDecision() *Decision
- func (m *MockOrchestrator) GetLastSignal(topic string) *ReceivedSignal
- func (m *MockOrchestrator) GetReceivedSignals() []ReceivedSignal
- func (m *MockOrchestrator) GetSignalCount(topic string) int
- func (m *MockOrchestrator) Reset()
- func (m *MockOrchestrator) Start(ctx context.Context) error
- func (m *MockOrchestrator) Stop() error
- func (m *MockOrchestrator) WaitForDecision(timeout time.Duration) (*Decision, error)
- func (m *MockOrchestrator) WaitForSignals(n int, timeout time.Duration) error
- type MockOrchestratorConfig
- type NewsFixtures
- type OrderExecutionFixtures
- type ReceivedSignal
- type RiskFixtures
- type TechnicalIndicatorFixtures
- type ToolCall
- type ToolHandler
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddMockMCPServer ¶
func AddMockMCPServer(config *agents.AgentConfig, serverName, url string)
AddMockMCPServer adds a mock MCP server configuration to an agent config. url is the Streamable HTTP endpoint of the server (e.g., "http://localhost:8093/mcp").
func GetTestMetricsPort ¶
GetTestMetricsPort returns a unique metrics port for testing
func TestAgentConfig ¶
func TestAgentConfig(name, agentType string) *agents.AgentConfig
TestAgentConfig creates a standard test agent configuration
Types ¶
type AgentTestHelper ¶
type AgentTestHelper struct {
// contains filtered or unexported fields
}
AgentTestHelper provides utilities for testing agents
func NewAgentTestHelper ¶
func NewAgentTestHelper(t *testing.T) *AgentTestHelper
NewAgentTestHelper creates a new test helper
func (*AgentTestHelper) AddCleanup ¶
func (h *AgentTestHelper) AddCleanup(fn func())
AddCleanup registers a cleanup function
func (*AgentTestHelper) AssertMCPCallArguments ¶
func (h *AgentTestHelper) AssertMCPCallArguments(server *MockMCPServer, toolName string, expectedArgs map[string]interface{})
AssertMCPCallArguments verifies the arguments of the last call to a tool
func (*AgentTestHelper) AssertMCPCallMade ¶
func (h *AgentTestHelper) AssertMCPCallMade(server *MockMCPServer, toolName string, expectedCount int)
AssertMCPCallMade verifies that a tool was called on a mock server
func (*AgentTestHelper) Cleanup ¶
func (h *AgentTestHelper) Cleanup()
Cleanup runs all registered cleanup functions
func (*AgentTestHelper) Context ¶
func (h *AgentTestHelper) Context() context.Context
Context returns the test context
func (*AgentTestHelper) CreateMockMarketDataServer ¶
func (h *AgentTestHelper) CreateMockMarketDataServer() *MockMCPServer
CreateMockMarketDataServer creates a mock market data server with common tools
func (*AgentTestHelper) CreateMockOrderExecutorServer ¶
func (h *AgentTestHelper) CreateMockOrderExecutorServer() *MockMCPServer
CreateMockOrderExecutorServer creates a mock order executor server
func (*AgentTestHelper) CreateMockTechnicalIndicatorsServer ¶
func (h *AgentTestHelper) CreateMockTechnicalIndicatorsServer() *MockMCPServer
CreateMockTechnicalIndicatorsServer creates a mock technical indicators server
func (*AgentTestHelper) CreateTestAgent ¶
func (h *AgentTestHelper) CreateTestAgent(name, agentType string, metricsPort int) *agents.BaseAgent
CreateTestAgent creates a basic test agent with no MCP servers
func (*AgentTestHelper) Logger ¶
func (h *AgentTestHelper) Logger() zerolog.Logger
Logger returns the test logger
func (*AgentTestHelper) SimulateAgentStep ¶
func (h *AgentTestHelper) SimulateAgentStep(agent *agents.BaseAgent) error
SimulateAgentStep simulates a single agent step without actually running the agent
func (*AgentTestHelper) WaitForCondition ¶
func (h *AgentTestHelper) WaitForCondition(condition func() bool, timeout time.Duration, message string) bool
WaitForCondition waits for a condition to be true or timeout
type CommonTools ¶
type CommonTools struct{}
CommonTools provides common MCP tool definitions for testing
func (CommonTools) CalculateRSITool ¶
func (CommonTools) CalculateRSITool() *mcp.Tool
CalculateRSITool returns a standard calculate_rsi tool definition
func (CommonTools) GetOHLCVTool ¶
func (CommonTools) GetOHLCVTool() *mcp.Tool
GetOHLCVTool returns a standard get_ohlcv tool definition
func (CommonTools) GetPriceTool ¶
func (CommonTools) GetPriceTool() *mcp.Tool
GetPriceTool returns a standard get_price tool definition
func (CommonTools) PlaceOrderTool ¶
func (CommonTools) PlaceOrderTool() *mcp.Tool
PlaceOrderTool returns a standard place_order tool definition
type Decision ¶
type Decision struct {
Action string // BUY, SELL, HOLD
Symbol string
Confidence float64
Reasoning string
Timestamp time.Time
BasedOn []string // Topics that contributed to decision
}
Decision represents a simulated orchestrator decision
func DefaultDecisionPolicy ¶
func DefaultDecisionPolicy(signals []ReceivedSignal) *Decision
DefaultDecisionPolicy is a simple majority voting policy
type DecisionPolicy ¶
type DecisionPolicy func(signals []ReceivedSignal) *Decision
DecisionPolicy determines how the mock orchestrator makes decisions
type MarketDataFixtures ¶
type MarketDataFixtures struct{}
MarketDataFixtures provides common market data for testing
func (MarketDataFixtures) SampleOHLCV ¶
func (MarketDataFixtures) SampleOHLCV() map[string]interface{}
SampleOHLCV returns sample OHLCV data for testing
func (MarketDataFixtures) SampleOrderBook ¶
func (MarketDataFixtures) SampleOrderBook() map[string]interface{}
SampleOrderBook returns sample order book data
func (MarketDataFixtures) SamplePrice ¶
func (MarketDataFixtures) SamplePrice() map[string]interface{}
SamplePrice returns sample price data
type MockMCPServer ¶
type MockMCPServer struct {
// contains filtered or unexported fields
}
MockMCPServer simulates an MCP server for testing agents
func NewMockMCPServer ¶
func NewMockMCPServer(name, version string) *MockMCPServer
NewMockMCPServer creates a new mock MCP server
func (*MockMCPServer) CallTool ¶
func (m *MockMCPServer) CallTool(ctx context.Context, params *mcp.CallToolParams) (*mcp.CallToolResult, error)
CallTool simulates calling a tool on the server
func (*MockMCPServer) GetCallCount ¶
func (m *MockMCPServer) GetCallCount(toolName string) int
GetCallCount returns the number of times a tool was called
func (*MockMCPServer) GetCalls ¶
func (m *MockMCPServer) GetCalls() []ToolCall
GetCalls returns all recorded tool calls
func (*MockMCPServer) GetLastCall ¶
func (m *MockMCPServer) GetLastCall(toolName string) *ToolCall
GetLastCall returns the last call for a specific tool
func (*MockMCPServer) GetName ¶
func (m *MockMCPServer) GetName() string
GetName returns the server name
func (*MockMCPServer) GetVersion ¶
func (m *MockMCPServer) GetVersion() string
GetVersion returns the server version
func (*MockMCPServer) ListTools ¶
func (m *MockMCPServer) ListTools(ctx context.Context, params *mcp.ListToolsParams) (*mcp.ListToolsResult, error)
ListTools returns all registered tools
func (*MockMCPServer) RegisterTool ¶
func (m *MockMCPServer) RegisterTool(tool *mcp.Tool, handler ToolHandler)
RegisterTool registers a tool with its handler
type MockOrchestrator ¶
type MockOrchestrator struct {
// contains filtered or unexported fields
}
MockOrchestrator simulates an orchestrator for testing agent signal publishing
Example ¶
ExampleMockOrchestrator demonstrates basic usage of the MockOrchestrator
package main
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/nats-io/nats.go"
"github.com/ajitpratap0/cryptofunk/internal/agents/testing"
)
func main() {
// Connect to NATS
nc, err := nats.Connect(nats.DefaultURL)
if err != nil {
fmt.Printf("Failed to connect to NATS: %v\n", err)
return
}
defer nc.Close()
// Create mock orchestrator
mo, err := testing.NewMockOrchestrator(testing.MockOrchestratorConfig{
NATSConn: nc,
Topics: []string{
"agents.analysis.technical",
"agents.analysis.orderbook",
},
})
if err != nil {
fmt.Printf("Failed to create mock orchestrator: %v\n", err)
return
}
// Start listening for signals
ctx := context.Background()
if err := mo.Start(ctx); err != nil {
fmt.Printf("Failed to start mock orchestrator: %v\n", err)
return
}
defer func() { _ = mo.Stop() }() // Example cleanup
// Simulate agent publishing a signal
signal := struct {
Symbol string `json:"symbol"`
Signal string `json:"signal"`
Confidence float64 `json:"confidence"`
}{
Symbol: "BTC/USDT",
Signal: "BUY",
Confidence: 0.85,
}
data, _ := json.Marshal(signal)
_ = nc.Publish("agents.analysis.technical", data) // Example - error acceptable
// Wait for signal to be received
if err := mo.WaitForSignals(1, 2*time.Second); err != nil {
fmt.Printf("Failed to receive signal: %v\n", err)
return
}
// Get received signals
signals := mo.GetReceivedSignals()
fmt.Printf("Received %d signal(s)\n", len(signals))
// Wait for decision
decision, err := mo.WaitForDecision(2 * time.Second)
if err != nil {
fmt.Printf("Failed to get decision: %v\n", err)
return
}
fmt.Printf("Decision: %s %s (confidence: %.2f)\n",
decision.Action, decision.Symbol, decision.Confidence)
// Example output when NATS is available:
// Received 1 signal(s)
// Decision: BUY BTC/USDT (confidence: 0.85)
}
Output:
Example (CustomDecisionPolicy) ¶
ExampleMockOrchestrator_customDecisionPolicy demonstrates custom decision-making
package main
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/nats-io/nats.go"
"github.com/ajitpratap0/cryptofunk/internal/agents/testing"
)
func main() {
nc, err := nats.Connect(nats.DefaultURL)
if err != nil {
fmt.Printf("Failed to connect to NATS: %v\n", err)
return
}
defer nc.Close()
// Custom policy that requires >0.90 confidence for BUY
customPolicy := func(signals []testing.ReceivedSignal) *testing.Decision {
if len(signals) == 0 {
return nil
}
// Extract signal data
var totalConfidence float64
var lastSymbol string
for _, sig := range signals {
if gs, ok := sig.Signal.(struct {
Symbol string `json:"symbol"`
Signal string `json:"signal"`
Confidence float64 `json:"confidence"`
}); ok {
totalConfidence += gs.Confidence
lastSymbol = gs.Symbol
}
}
avgConfidence := totalConfidence / float64(len(signals))
// High confidence threshold
if avgConfidence > 0.90 {
return &testing.Decision{
Action: "BUY",
Symbol: lastSymbol,
Confidence: avgConfidence,
Reasoning: "High confidence threshold met",
}
}
return &testing.Decision{
Action: "HOLD",
Symbol: lastSymbol,
Confidence: avgConfidence,
Reasoning: "Confidence threshold not met",
}
}
// Create orchestrator with custom policy
mo, err := testing.NewMockOrchestrator(testing.MockOrchestratorConfig{
NATSConn: nc,
Topics: []string{"agents.analysis.technical"},
DecisionPolicy: customPolicy,
})
if err != nil {
fmt.Printf("Failed to create mock orchestrator: %v\n", err)
return
}
ctx := context.Background()
if err := mo.Start(ctx); err != nil {
fmt.Printf("Failed to start: %v\n", err)
return
}
defer func() { _ = mo.Stop() }() // Example cleanup
// Publish low confidence signal
signal := struct {
Symbol string `json:"symbol"`
Signal string `json:"signal"`
Confidence float64 `json:"confidence"`
}{
Symbol: "ETH/USDT",
Signal: "BUY",
Confidence: 0.80, // Below 0.90 threshold
}
data, _ := json.Marshal(signal)
_ = nc.Publish("agents.analysis.technical", data) // Example - error acceptable
_ = mo.WaitForSignals(1, 2*time.Second) // Example - timeout acceptable
decision, _ := mo.WaitForDecision(2 * time.Second)
fmt.Printf("Decision: %s (reasoning: %s)\n",
decision.Action, decision.Reasoning)
// Example output when NATS is available:
// Decision: HOLD (reasoning: Confidence threshold not met)
}
Output:
Example (MultipleAgents) ¶
ExampleMockOrchestrator_multipleAgents demonstrates aggregating signals from multiple agents
package main
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/nats-io/nats.go"
"github.com/ajitpratap0/cryptofunk/internal/agents/testing"
)
func main() {
nc, err := nats.Connect(nats.DefaultURL)
if err != nil {
fmt.Printf("Failed to connect to NATS: %v\n", err)
return
}
defer nc.Close()
mo, err := testing.NewMockOrchestrator(testing.MockOrchestratorConfig{
NATSConn: nc,
Topics: []string{
"agents.analysis.technical",
"agents.analysis.orderbook",
"agents.analysis.sentiment",
},
})
if err != nil {
fmt.Printf("Failed to create mock orchestrator: %v\n", err)
return
}
ctx := context.Background()
_ = mo.Start(ctx) // Example - error logged
defer func() { _ = mo.Stop() }() // Example cleanup
// Technical agent signal
techSignal := struct {
Symbol string `json:"symbol"`
Signal string `json:"signal"`
Confidence float64 `json:"confidence"`
}{Symbol: "BTC/USDT", Signal: "BUY", Confidence: 0.85}
techData, _ := json.Marshal(techSignal)
_ = nc.Publish("agents.analysis.technical", techData) // Example - error acceptable
// Order book agent signal
obSignal := struct {
Symbol string `json:"symbol"`
Signal string `json:"signal"`
Confidence float64 `json:"confidence"`
}{Symbol: "BTC/USDT", Signal: "BUY", Confidence: 0.80}
obData, _ := json.Marshal(obSignal)
_ = nc.Publish("agents.analysis.orderbook", obData) // Example - error acceptable
// Sentiment agent signal
sentSignal := struct {
Symbol string `json:"symbol"`
Signal string `json:"signal"`
Confidence float64 `json:"confidence"`
}{Symbol: "BTC/USDT", Signal: "BULLISH", Confidence: 0.75}
sentData, _ := json.Marshal(sentSignal)
_ = nc.Publish("agents.analysis.sentiment", sentData) // Example - error acceptable
// Wait for all signals
_ = mo.WaitForSignals(3, 2*time.Second) // Example - timeout acceptable
// Check signal counts per topic
fmt.Printf("Technical signals: %d\n", mo.GetSignalCount("agents.analysis.technical"))
fmt.Printf("Order book signals: %d\n", mo.GetSignalCount("agents.analysis.orderbook"))
fmt.Printf("Sentiment signals: %d\n", mo.GetSignalCount("agents.analysis.sentiment"))
// Get decision based on all signals
decision, _ := mo.WaitForDecision(2 * time.Second)
fmt.Printf("Final decision: %s (confidence: %.2f)\n",
decision.Action, decision.Confidence)
// Example output when NATS is available:
// Technical signals: 1
// Order book signals: 1
// Sentiment signals: 1
// Final decision: BUY (confidence: 0.80)
}
Output:
Example (Testing) ¶
ExampleMockOrchestrator_testing demonstrates using MockOrchestrator in tests
package main
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/nats-io/nats.go"
"github.com/ajitpratap0/cryptofunk/internal/agents/testing"
)
func main() {
// This example shows how to use MockOrchestrator to test that agents
// properly publish signals to NATS
nc, _ := nats.Connect(nats.DefaultURL)
defer nc.Close()
mo, _ := testing.NewMockOrchestrator(testing.MockOrchestratorConfig{
NATSConn: nc,
Topics: []string{"agents.analysis.technical"},
})
ctx := context.Background()
_ = mo.Start(ctx) // Example - error logged
defer func() { _ = mo.Stop() }() // Example cleanup
// Simulate agent publishing
signal := struct {
Symbol string `json:"symbol"`
Signal string `json:"signal"`
Confidence float64 `json:"confidence"`
}{Symbol: "BTC/USDT", Signal: "BUY", Confidence: 0.90}
data, _ := json.Marshal(signal)
_ = nc.Publish("agents.analysis.technical", data) // Example - error acceptable
// Verify signal was received
if err := mo.WaitForSignals(1, 2*time.Second); err != nil {
fmt.Printf("Test failed: signal not received\n")
return
}
// Verify signal content
lastSignal := mo.GetLastSignal("agents.analysis.technical")
if lastSignal != nil {
fmt.Println("Test passed: signal received and recorded")
}
// Verify decision was made
decision := mo.GetLastDecision()
if decision != nil && decision.Action == "BUY" {
fmt.Println("Test passed: correct decision made")
}
// Example output when NATS is available:
// Test passed: signal received and recorded
// Test passed: correct decision made
}
Output:
func NewMockOrchestrator ¶
func NewMockOrchestrator(config MockOrchestratorConfig) (*MockOrchestrator, error)
NewMockOrchestrator creates a new mock orchestrator
func (*MockOrchestrator) GetDecisions ¶
func (m *MockOrchestrator) GetDecisions() []Decision
GetDecisions returns all simulated decisions
func (*MockOrchestrator) GetLastDecision ¶
func (m *MockOrchestrator) GetLastDecision() *Decision
GetLastDecision returns the most recent decision
func (*MockOrchestrator) GetLastSignal ¶
func (m *MockOrchestrator) GetLastSignal(topic string) *ReceivedSignal
GetLastSignal returns the last signal received from a specific topic
func (*MockOrchestrator) GetReceivedSignals ¶
func (m *MockOrchestrator) GetReceivedSignals() []ReceivedSignal
GetReceivedSignals returns all recorded signals
func (*MockOrchestrator) GetSignalCount ¶
func (m *MockOrchestrator) GetSignalCount(topic string) int
GetSignalCount returns the number of signals received from a specific topic
func (*MockOrchestrator) Reset ¶
func (m *MockOrchestrator) Reset()
Reset clears all recorded signals and decisions
func (*MockOrchestrator) Start ¶
func (m *MockOrchestrator) Start(ctx context.Context) error
Start begins listening for agent signals
func (*MockOrchestrator) Stop ¶
func (m *MockOrchestrator) Stop() error
Stop unsubscribes from all topics and cleans up
func (*MockOrchestrator) WaitForDecision ¶
func (m *MockOrchestrator) WaitForDecision(timeout time.Duration) (*Decision, error)
WaitForDecision waits for at least one decision to be made or timeout
func (*MockOrchestrator) WaitForSignals ¶
func (m *MockOrchestrator) WaitForSignals(n int, timeout time.Duration) error
WaitForSignals waits for at least n signals to be received or timeout
type MockOrchestratorConfig ¶
type MockOrchestratorConfig struct {
NATSConn *nats.Conn
Topics []string
DecisionPolicy DecisionPolicy
}
MockOrchestratorConfig configures the mock orchestrator
type NewsFixtures ¶
type NewsFixtures struct{}
NewsFixtures provides sentiment/news data for testing
func (NewsFixtures) SampleFearGreedIndex ¶
func (NewsFixtures) SampleFearGreedIndex() map[string]interface{}
SampleFearGreedIndex returns sample Fear & Greed Index data
func (NewsFixtures) SampleNews ¶
func (NewsFixtures) SampleNews() map[string]interface{}
SampleNews returns sample news articles
type OrderExecutionFixtures ¶
type OrderExecutionFixtures struct{}
OrderExecutionFixtures provides order execution data for testing
func (OrderExecutionFixtures) SampleLimitOrder ¶
func (OrderExecutionFixtures) SampleLimitOrder() map[string]interface{}
SampleLimitOrder returns sample limit order result
func (OrderExecutionFixtures) SampleMarketOrder ¶
func (OrderExecutionFixtures) SampleMarketOrder() map[string]interface{}
SampleMarketOrder returns sample market order result
type ReceivedSignal ¶
type ReceivedSignal struct {
Topic string
Signal interface{} // TechnicalSignal, OrderBookSignal, or SentimentSignal
RawData []byte
Timestamp time.Time
}
ReceivedSignal represents a signal received from an agent
type RiskFixtures ¶
type RiskFixtures struct{}
RiskFixtures provides risk management data for testing
func (RiskFixtures) SamplePortfolio ¶
func (RiskFixtures) SamplePortfolio() map[string]interface{}
SamplePortfolio returns sample portfolio data
func (RiskFixtures) SampleRiskLimits ¶
func (RiskFixtures) SampleRiskLimits() map[string]interface{}
SampleRiskLimits returns sample risk limits
type TechnicalIndicatorFixtures ¶
type TechnicalIndicatorFixtures struct{}
TechnicalIndicatorFixtures provides technical indicator data for testing
func (TechnicalIndicatorFixtures) SampleBollinger ¶
func (TechnicalIndicatorFixtures) SampleBollinger() map[string]interface{}
SampleBollinger returns sample Bollinger Bands data
func (TechnicalIndicatorFixtures) SampleMACD ¶
func (TechnicalIndicatorFixtures) SampleMACD() map[string]interface{}
SampleMACD returns sample MACD data
func (TechnicalIndicatorFixtures) SampleRSI ¶
func (TechnicalIndicatorFixtures) SampleRSI() map[string]interface{}
SampleRSI returns sample RSI data