Documentation
¶
Overview ¶
## Service Testing - **Lifecycle Management**: Test service creation, management, and deletion - **Dependency Management**: Validate service dependency resolution - **State Transitions**: Test service state changes and event handling - **Integration**: Test service interaction with other system components
Mock MCP Server Support ¶
The testing framework includes comprehensive mock MCP server functionality:
- **Mock Tool Definitions**: Define tools with configurable responses - **Conditional Responses**: Different responses based on input args - **Template-Based Responses**: Dynamic response generation using Go templates - **Error Simulation**: Simulate various error conditions and failures - **Standalone Mode**: Run mock servers independently for external testing
Mock servers can be embedded in test scenarios or run standalone:
# Embedded in test scenario
mcpServers:
- name: "mock-kubernetes"
type: "mock"
tools:
- name: "kubectl_get_pods"
responses:
- condition: {namespace: "default"}
response: "pod1\npod2\npod3"
# Standalone mode
muster test --mock-mcp-server --mock-config=mock-config.yaml
Extension Points ¶
The testing framework is designed for extensibility through several mechanisms:
## Custom Test Steps - Implement custom step types by extending the TestStep interface - Register custom step handlers with the TestRunner - Support for domain-specific validation logic
## Custom Reporters - Implement the TestReporter interface for custom output formats - Support for custom metrics collection and analysis - Integration with external monitoring and alerting systems
## Custom Scenario Loaders - Implement the TestScenarioLoader interface for alternative configuration sources - Support for dynamic scenario generation - Integration with external test management systems
Thread Safety ¶
The testing framework is designed with thread safety as a core requirement:
- **Concurrent Execution**: All components support concurrent access - **Immutable Data**: Test scenarios and configuration are immutable after loading - **Thread-Safe Reporting**: Reporter implementations handle concurrent access - **Resource Isolation**: Each test execution maintains isolated state
**Safety Guarantees**: - TestRunner can safely execute multiple scenarios concurrently - MCPTestClient instances are thread-safe for concurrent tool calls - TestReporter can safely handle concurrent progress and result reporting - Shared resources (connections, files) are protected with appropriate synchronization
Performance Characteristics ¶
The framework is optimized for both development and CI/CD environments:
## Execution Performance - **Parallel Execution**: Configurable worker pools (1-10 workers recommended) - **Connection Pooling**: Reuse MCP connections across multiple test steps - **Lazy Loading**: Scenarios loaded only when needed - **Memory Efficiency**: Streaming result processing for large test suites
## Scaling Characteristics - **Linear Scaling**: Performance scales linearly with parallel worker count - **Memory Usage**: O(n) memory usage relative to active scenarios - **Network Efficiency**: Connection reuse and request batching - **Resource Cleanup**: Automatic cleanup prevents resource leaks
**Performance Recommendations**: - Use 2-4 parallel workers for development testing - Use 4-8 parallel workers for CI/CD environments - Implement timeouts appropriate for your environment (30s-5m recommended) - Monitor memory usage with large test suites (>100 scenarios)
Usage Patterns ¶
## Basic Testing
```bash muster test # Run all tests muster test --category=behavioral # Category-specific muster test --concept=serviceclass # Concept-specific muster test --scenario=basic-create # Scenario-specific ```
## Advanced Configuration
```bash muster test --parallel=50 --timeout=10m --fail-fast muster test --verbose --debug --output-format=json ```
## CI/CD Integration
```bash muster test --category=integration --output-format=junit --report-file=results.xml ```
## Mock MCP Server Testing
```bash # Run with mock servers defined in scenarios muster test --scenario=test-with-mock # Run standalone mock server muster test --mock-mcp-server --mock-config=mock-tools.yaml ```
Dependencies ¶
The testing framework requires: - A running muster aggregator server (muster serve) - MCP protocol communication capabilities - Access to all core_* MCP tools exposed by the aggregator - Write access for temporary files and test artifacts
Error Handling ¶
The framework implements comprehensive error handling: - **Graceful Degradation**: Continue execution when possible - **Detailed Error Messages**: Context-rich error information - **Error Classification**: Distinguish between test failures and framework errors - **Recovery Mechanisms**: Automatic retry and fallback logic where appropriate
Integration with CI/CD ¶
The framework provides first-class CI/CD support: - **Structured Output**: JSON, JUnit XML, and TAP output formats - **Exit Codes**: Proper exit codes for automation (0=success, 1=failures, 2=errors) - **Report Files**: File-based output for artifact collection - **Environment Integration**: Support for CI environment variables and configuration
For complete usage documentation, see docs/testing/README.md For scenario authoring guidance, see docs/testing/scenarios.md For comprehensive examples, see docs/testing/examples/
Package testing provides test helper tools for BDD test scenarios. These tools allow test scenarios to interact with mock infrastructure components that run in the test orchestrator process.
Index ¶
- Constants
- func CleanupStaleMusterTestProcesses(logger TestLogger, debug bool)
- func FormatValidationResults(results *ScenarioValidationResults, verbose bool) string
- func GenerateScenarioPrefix(scenarioName string) string
- func GetDefaultScenarioPath() string
- func GetScenarioPath(configPath string) string
- func IsTestTool(toolName string) bool
- func LoadSchemaFromFile(filename string) (map[string]interface{}, error)
- type ExecutionMode
- type InstanceLogs
- type MCPServerConfig
- type MCPServerOAuthConfig
- type MCPTestClient
- type MainConfig
- type MockHTTPServerInfo
- type MockOAuthServerConfig
- type MockOAuthServerInfo
- type MusterInstance
- type MusterInstanceManager
- type MusterPreConfiguration
- type RetryConfig
- type ScenarioContext
- type ScenarioState
- type ScenarioValidationResult
- type ScenarioValidationResults
- type ServiceClassConfig
- type ServiceConfig
- type StepValidationResult
- type StructuredTestReporter
- type TemplateProcessor
- type TestCategory
- type TestConcept
- type TestConfiguration
- type TestExpectation
- type TestFramework
- type TestLogger
- type TestReporter
- type TestResult
- type TestRunner
- type TestScenario
- type TestScenarioLoader
- type TestScenarioResult
- type TestStep
- type TestStepResult
- type TestSuiteResult
- type TestToolContent
- type TestToolResult
- type TestToolsHandler
- func (h *TestToolsHandler) CloseAllUserClients()
- func (h *TestToolsHandler) GetCurrentClient() MCPTestClient
- func (h *TestToolsHandler) GetCurrentUserName() string
- func (h *TestToolsHandler) HandleTestTool(ctx context.Context, toolName string, args map[string]interface{}) (interface{}, error)
- func (h *TestToolsHandler) HasUser(name string) bool
- func (h *TestToolsHandler) SetMCPClient(client MCPTestClient)
- func (h *TestToolsHandler) SwitchToUser(name string) bool
- type TrustedIssuerConfig
- type ValidationError
- type WorkflowConfig
Constants ¶
const ( // TestToolSimulateOAuthCallback simulates completing an OAuth flow for testing. TestToolSimulateOAuthCallback = "test_simulate_oauth_callback" // TestToolInjectToken directly injects an access token for testing. TestToolInjectToken = "test_inject_token" // TestToolGetOAuthServerInfo returns information about mock OAuth servers. TestToolGetOAuthServerInfo = "test_get_oauth_server_info" // TestToolAdvanceOAuthClock advances the mock OAuth server's clock for testing. TestToolAdvanceOAuthClock = "test_advance_oauth_clock" // TestToolReadAuthStatus reads the auth://status resource to verify auth state. TestToolReadAuthStatus = "test_read_auth_status" // TestToolRevokeToken revokes a token on the mock OAuth server for testing. TestToolRevokeToken = "test_revoke_token" // TestToolCreateUser creates a new user session for multi-user testing. TestToolCreateUser = "test_create_user" // TestToolSwitchUser switches to a different user session for multi-user testing. TestToolSwitchUser = "test_switch_user" // TestToolListToolsForUser lists tools visible to a specific user. TestToolListToolsForUser = "test_list_tools_for_user" // TestToolGetCurrentUser returns the current active user name. TestToolGetCurrentUser = "test_get_current_user" // TestToolSimulateMusterReauth simulates re-authentication to muster with a new token // while preserving the session ID. Used to test proactive SSO re-triggering. TestToolSimulateMusterReauth = "test_simulate_muster_reauth" // TestToolMusterAuthLogin simulates `muster auth login` by completing the OAuth // callback to muster's token store. This is required for SSO token forwarding tests. TestToolMusterAuthLogin = "test_muster_auth_login" )
Test tool name constants for BDD test scenarios.
Variables ¶
This section is empty.
Functions ¶
func CleanupStaleMusterTestProcesses ¶
func CleanupStaleMusterTestProcesses(logger TestLogger, debug bool)
CleanupStaleMusterTestProcesses kills any muster processes that were left behind from previous test runs. It identifies test processes by looking for muster serve commands with --config-path pointing to /tmp/muster-test-* directories.
This should be called at the start of each test suite to ensure a clean slate. The function is best-effort and logs errors rather than returning them, since cleanup failures should not block test execution.
func FormatValidationResults ¶
func FormatValidationResults(results *ScenarioValidationResults, verbose bool) string
FormatValidationResults formats validation results for CLI output
func GenerateScenarioPrefix ¶
GenerateScenarioPrefix generates a short unique prefix for a scenario. The prefix is formatted as [XXXXXX] where XXXXXX is derived from the scenario name. For readability, it combines: - First 3 chars of the cleaned scenario name - First 3 chars of a SHA256 hash of the full name (for uniqueness)
func GetDefaultScenarioPath ¶
func GetDefaultScenarioPath() string
GetDefaultScenarioPath returns the default path for test scenarios
func GetScenarioPath ¶
GetScenarioPath determines the actual scenario path to use, handling empty/default cases
func IsTestTool ¶
IsTestTool returns true if the tool name is a test helper tool.
func LoadSchemaFromFile ¶
LoadSchemaFromFile loads a JSON schema from file
Types ¶
type ExecutionMode ¶
type ExecutionMode string
ExecutionMode represents the mode of test execution
const ( // ExecutionModeCLI represents command line interface execution ExecutionModeCLI ExecutionMode = "cli" // ExecutionModeMCPServer represents MCP server execution via stdio ExecutionModeMCPServer ExecutionMode = "mcp-server" )
type InstanceLogs ¶
type InstanceLogs struct {
// Stdout contains the standard output
Stdout string
// Stderr contains the standard error output
Stderr string
// Combined contains both stdout and stderr in chronological order
Combined string
}
InstanceLogs contains the captured logs from an muster instance
type MCPServerConfig ¶
type MCPServerConfig struct {
// Name is the unique identifier for the MCP server
Name string `yaml:"name"`
// Config contains the server-specific configuration (can include tools for mock servers)
Config map[string]interface{} `yaml:"config"`
}
MCPServerConfig represents an MCP server configuration
type MCPServerOAuthConfig ¶
type MCPServerOAuthConfig struct {
// Required indicates this server requires OAuth authentication
Required bool `yaml:"required"`
// MockOAuthServerRef references a mock OAuth server by name
MockOAuthServerRef string `yaml:"mock_oauth_server_ref"`
// Scope is the required OAuth scope
Scope string `yaml:"scope,omitempty"`
}
MCPServerOAuthConfig defines OAuth protection for an MCP server in tests
type MCPTestClient ¶
type MCPTestClient interface {
// Connect establishes connection to the MCP aggregator
Connect(ctx context.Context, endpoint string) error
// ConnectWithAuth establishes connection to the MCP aggregator with an access token.
// This is used when muster's OAuth server is enabled and requires authentication.
ConnectWithAuth(ctx context.Context, endpoint, accessToken string) error
// CallTool invokes an MCP tool with the given args
CallTool(ctx context.Context, toolName string, args map[string]interface{}) (interface{}, error)
// ListTools returns available MCP tools
ListTools(ctx context.Context) ([]string, error)
// ListToolsWithSchemas returns available MCP tools with their full schemas
ListToolsWithSchemas(ctx context.Context) ([]mcp.Tool, error)
// ReadResource reads an MCP resource by URI
ReadResource(ctx context.Context, uri string) (*mcp.ReadResourceResult, error)
// Close closes the MCP connection
Close() error
// GetSessionID returns the client's session ID (may be empty if not set)
GetSessionID() string
// ReconnectWithSession reconnects using a specific session ID and new access token.
// This is used to test proactive SSO re-triggering when a token changes for the same session.
ReconnectWithSession(ctx context.Context, endpoint, accessToken, sessionID string) error
}
MCPTestClient interface defines the MCP client for testing
func NewMCPTestClient ¶
func NewMCPTestClient(debug bool) MCPTestClient
NewMCPTestClient creates a new MCP test client
func NewMCPTestClientWithLogger ¶
func NewMCPTestClientWithLogger(debug bool, logger TestLogger) MCPTestClient
NewMCPTestClientWithLogger creates a new MCP test client with custom logger
type MainConfig ¶
type MainConfig struct {
// Config contains the main configuration
Config map[string]interface{} `yaml:"config"`
}
MainConfig represents the main muster configuration
type MockHTTPServerInfo ¶
type MockHTTPServerInfo struct {
// Name is the name of the MCP server
Name string
// Port is the port the mock HTTP server is listening on
Port int
// Transport is the transport type (sse or streamable-http)
Transport string
// Endpoint is the full URL endpoint for the server
Endpoint string
}
MockHTTPServerInfo contains information about a running mock HTTP server
type MockOAuthServerConfig ¶
type MockOAuthServerConfig struct {
// Name is the unique identifier for this OAuth server
Name string `yaml:"name"`
// Issuer is the OAuth issuer URL (auto-generated if not specified)
Issuer string `yaml:"issuer,omitempty"`
// Scopes are the scopes this OAuth server accepts
Scopes []string `yaml:"scopes,omitempty"`
// AutoApprove automatically approves authentication requests
AutoApprove bool `yaml:"auto_approve,omitempty"`
// PKCERequired enforces PKCE flow
PKCERequired bool `yaml:"pkce_required,omitempty"`
// TokenLifetime is how long tokens are valid (e.g., "1h", "30m")
TokenLifetime string `yaml:"token_lifetime,omitempty"`
// ClientID is the expected OAuth client ID
ClientID string `yaml:"client_id,omitempty"`
// ClientSecret is the expected OAuth client secret
ClientSecret string `yaml:"client_secret,omitempty"`
// SimulateError can simulate error conditions
SimulateError string `yaml:"simulate_error,omitempty"`
// UseMockClock enables a mock clock for testing token expiry
// When true, the test_advance_oauth_clock tool can be used to
// advance time without waiting
UseMockClock bool `yaml:"use_mock_clock,omitempty"`
// UseAsMusterOAuthServer configures this mock OAuth server as muster's
// OAuth server (aggregator.oauthServer), enabling SSO token forwarding
// tests where muster itself requires OAuth authentication.
// When true, the aggregator will be configured with oauthServer.enabled=true
// and the issuer will be set to this mock server's URL.
UseAsMusterOAuthServer bool `yaml:"use_as_muster_oauth_server,omitempty"`
// TrustedIssuers configures RFC 8693 token exchange support.
// When configured, this OAuth server can exchange tokens from the listed
// issuers for tokens valid on this server. This enables cross-cluster SSO testing.
// Each entry maps a connector_id to a trusted OAuth server name.
TrustedIssuers []TrustedIssuerConfig `yaml:"trusted_issuers,omitempty"`
// UseTLS enables HTTPS mode with a self-signed certificate.
// This is required for OAuth servers used as token exchange targets,
// since RFC 8693 token exchange endpoints must use HTTPS for security.
// Note: This is automatically set to true when UseAsMusterOAuthServer is true.
UseTLS bool `yaml:"use_tls,omitempty"`
}
MockOAuthServerConfig defines a mock OAuth server for testing
type MockOAuthServerInfo ¶
type MockOAuthServerInfo struct {
// Name is the unique identifier for this OAuth server
Name string
// Port is the port the OAuth server is listening on
Port int
// IssuerURL is the OAuth issuer URL
IssuerURL string
// AccessToken is a pre-generated access token for test framework authentication.
// This is only set when the OAuth server is used as muster's OAuth server
// (UseAsMusterOAuthServer=true), allowing the test framework to authenticate
// with muster without implementing the full OAuth browser flow.
AccessToken string
// IDToken is the ID token from the OAuth response.
// This is used for SSO token forwarding tests.
IDToken string
// UseAsMusterOAuthServer indicates this OAuth server is used as muster's OAuth server.
UseAsMusterOAuthServer bool
}
MockOAuthServerInfo contains info about a running mock OAuth server
type MusterInstance ¶
type MusterInstance struct {
// ID is the unique identifier for this instance
ID string
// ConfigPath is the path to the temporary configuration directory
ConfigPath string
// Port is the port the instance is listening on
Port int
// Endpoint is the full MCP endpoint URL
Endpoint string
// Process is the running muster serve process
Process *os.Process
// StartTime when the instance was started
StartTime time.Time
// Logs contains the collected stdout and stderr from the instance
Logs *InstanceLogs
// ExpectedTools contains the list of tools expected to be available from MCP servers
ExpectedTools []string
// ExpectedServiceClasses contains the list of ServiceClasses expected to be available
ExpectedServiceClasses []string
// ExpectedMCPServers contains the list of MCP server names expected to be registered.
// This includes OAuth-protected servers which may be in "auth_required" state.
// Used by WaitForReady to ensure servers are registered before tests run.
ExpectedMCPServers []string
// MockHTTPServers contains references to mock HTTP servers started for this instance
MockHTTPServers map[string]*MockHTTPServerInfo
// MockOAuthServers contains references to mock OAuth servers started for this instance
MockOAuthServers map[string]*MockOAuthServerInfo
// MusterOAuthAccessToken is the access token for authenticating with muster's OAuth server.
// This is set when a mock OAuth server is configured with UseAsMusterOAuthServer=true.
// The test framework uses this token to authenticate with muster without a browser flow.
MusterOAuthAccessToken string
}
MusterInstance represents a managed muster serve instance
type MusterInstanceManager ¶
type MusterInstanceManager interface {
// CreateInstance creates a new muster serve instance with the given configuration.
// The logger parameter allows scenario-specific logging with prefixes for parallel execution.
CreateInstance(ctx context.Context, scenarioName string, config *MusterPreConfiguration, logger TestLogger) (*MusterInstance, error)
// DestroyInstance stops and cleans up an muster serve instance.
// The logger parameter allows scenario-specific logging with prefixes for parallel execution.
DestroyInstance(ctx context.Context, instance *MusterInstance, logger TestLogger) error
// WaitForReady waits for an instance to be ready to accept connections.
// The logger parameter allows scenario-specific logging with prefixes for parallel execution.
WaitForReady(ctx context.Context, instance *MusterInstance, logger TestLogger) error
}
MusterInstanceManager manages muster serve instances for testing
func NewMusterInstanceManagerWithConfig ¶
func NewMusterInstanceManagerWithConfig(debug bool, basePort int, logger TestLogger, keepTempConfig bool) (MusterInstanceManager, error)
NewMusterInstanceManagerWithConfig creates a new muster instance manager with custom logger and config options
func NewMusterInstanceManagerWithLogger ¶
func NewMusterInstanceManagerWithLogger(debug bool, basePort int, logger TestLogger) (MusterInstanceManager, error)
NewMusterInstanceManagerWithLogger creates a new muster instance manager with custom logger
type MusterPreConfiguration ¶
type MusterPreConfiguration struct {
// MCPServers defines MCP server configurations to load
MCPServers []MCPServerConfig `yaml:"mcp_servers,omitempty"`
// Workflows defines workflow definitions to load
Workflows []WorkflowConfig `yaml:"workflows,omitempty"`
// ServiceClasses defines service class definitions to load
ServiceClasses []ServiceClassConfig `yaml:"service_classes,omitempty"`
// Services defines service instance definitions to load
Services []ServiceConfig `yaml:"services,omitempty"`
// MainConfig defines the main muster configuration
MainConfig *MainConfig `yaml:"main_config,omitempty"`
// MockOAuthServers defines mock OAuth servers to start for testing
MockOAuthServers []MockOAuthServerConfig `yaml:"mock_oauth_servers,omitempty"`
}
MusterPreConfiguration defines how to pre-configure an muster serve instance
type RetryConfig ¶
type RetryConfig struct {
// Count is the number of retry attempts
Count int `yaml:"count"`
// Delay between retry attempts
Delay time.Duration `yaml:"delay"`
// BackoffMultiplier for exponential backoff
BackoffMultiplier float64 `yaml:"backoff_multiplier,omitempty"`
}
RetryConfig defines retry behavior for test steps
type ScenarioContext ¶
type ScenarioContext struct {
// contains filtered or unexported fields
}
ScenarioContext holds the execution context for a test scenario including stored results from previous steps for template variable resolution
func NewScenarioContext ¶
func NewScenarioContext() *ScenarioContext
NewScenarioContext creates a new scenario execution context
func (*ScenarioContext) GetAllStoredResults ¶
func (sc *ScenarioContext) GetAllStoredResults() map[string]interface{}
GetAllStoredResults returns a copy of all stored results for debugging
func (*ScenarioContext) StoreResult ¶
func (sc *ScenarioContext) StoreResult(name string, result interface{})
StoreResult stores a step result under the given variable name
type ScenarioState ¶
type ScenarioState struct {
Scenario TestScenario `json:"scenario"`
StartTime time.Time `json:"start_time"`
StepResults []TestStepResult `json:"step_results"`
Status string `json:"status"` // "running", "completed", "failed"
}
ScenarioState tracks the state of a running scenario
type ScenarioValidationResult ¶
type ScenarioValidationResult struct {
ScenarioName string `json:"scenario_name"`
Valid bool `json:"valid"`
Errors []ValidationError `json:"errors,omitempty"`
StepResults []StepValidationResult `json:"step_results"`
}
ScenarioValidationResult represents the validation result for a single scenario
type ScenarioValidationResults ¶
type ScenarioValidationResults struct {
TotalScenarios int `json:"total_scenarios"`
ValidScenarios int `json:"valid_scenarios"`
TotalErrors int `json:"total_errors"`
ScenarioResults []ScenarioValidationResult `json:"scenario_results"`
ValidationSummary map[string]int `json:"validation_summary"`
}
ScenarioValidationResults represents the results of validating multiple scenarios
func ValidateScenariosAgainstSchema ¶
func ValidateScenariosAgainstSchema(scenarios []TestScenario, schema map[string]interface{}, verbose, debug bool) *ScenarioValidationResults
ValidateScenariosAgainstSchema validates scenarios against the API schema
type ServiceClassConfig ¶
type ServiceClassConfig map[string]interface{}
ServiceClassConfig represents a service class configuration
type ServiceConfig ¶
type ServiceConfig struct {
// Name is the unique identifier for the service instance
Name string `yaml:"name"`
// Config contains the service instance definition
Config map[string]interface{} `yaml:"config"`
}
ServiceConfig represents a service instance configuration
type StepValidationResult ¶
type StepValidationResult struct {
StepID string `json:"step_id"`
Tool string `json:"tool"`
Valid bool `json:"valid"`
Errors []ValidationError `json:"errors,omitempty"`
}
StepValidationResult represents the validation result for a single step
type StructuredTestReporter ¶
type StructuredTestReporter interface {
TestReporter
// GetCurrentSuiteResult returns the current test suite result
GetCurrentSuiteResult() *TestSuiteResult
// GetScenarioStates returns the current state of all scenarios
GetScenarioStates() map[string]*ScenarioState
// GetCurrentResults returns the current scenario results
GetCurrentResults() []TestScenarioResult
// GetResultsAsJSON returns the current results as JSON
GetResultsAsJSON() (string, error)
// IsVerbose returns whether verbose reporting is enabled
IsVerbose() bool
// IsDebug returns whether debug reporting is enabled
IsDebug() bool
}
StructuredTestReporter extends TestReporter with methods for structured data access This is typically used in MCP server mode where results need to be queried programmatically
type TemplateProcessor ¶
type TemplateProcessor struct {
// contains filtered or unexported fields
}
TemplateProcessor handles template variable resolution in test step arguments using the existing enhanced template engine
func NewTemplateProcessor ¶
func NewTemplateProcessor(context *ScenarioContext) *TemplateProcessor
NewTemplateProcessor creates a new template processor with the given scenario context
func (*TemplateProcessor) ResolveArgs ¶
func (tp *TemplateProcessor) ResolveArgs(args map[string]interface{}) (map[string]interface{}, error)
ResolveArgs processes a map of arguments and resolves any template variables
type TestCategory ¶
type TestCategory string
TestCategory represents the category of tests to execute
const ( // CategoryBehavioral represents BDD-style behavioral tests CategoryBehavioral TestCategory = "behavioral" // CategoryIntegration represents integration and end-to-end tests CategoryIntegration TestCategory = "integration" )
type TestConcept ¶
type TestConcept string
TestConcept represents the core muster concept being tested
const ( // ConceptServiceClass represents ServiceClass management tests ConceptServiceClass TestConcept = "serviceclass" // ConceptWorkflow represents Workflow execution tests ConceptWorkflow TestConcept = "workflow" // ConceptMCPServer represents MCPServer management tests ConceptMCPServer TestConcept = "mcpserver" // ConceptService represents Service lifecycle tests ConceptService TestConcept = "service" )
type TestConfiguration ¶
type TestConfiguration struct {
// Timeout is the overall test execution timeout
Timeout time.Duration `yaml:"timeout"`
// Category filter for test execution
Category TestCategory `yaml:"category,omitempty"`
// Concept filter for test execution
Concept TestConcept `yaml:"concept,omitempty"`
// Scenario filter for specific scenario execution
Scenario string `yaml:"scenario,omitempty"`
// Parallel is the number of parallel test workers
Parallel int `yaml:"parallel"`
// FailFast stops execution on first failure
FailFast bool `yaml:"fail_fast"`
// Verbose enables detailed output
Verbose bool `yaml:"verbose"`
// Debug enables debug logging and MCP tracing
Debug bool `yaml:"debug"`
// ConfigPath is the path to test scenario definitions
ConfigPath string `yaml:"config_path,omitempty"`
// ReportPath is the path to save detailed test reports
ReportPath string `yaml:"report_path,omitempty"`
// BasePort is the starting port number for muster instances
BasePort int `yaml:"base_port,omitempty"`
// KeepTempConfig keeps temporary config directory after test execution
KeepTempConfig bool `yaml:"keep_temp_config,omitempty"`
}
TestConfiguration defines the overall test execution configuration
type TestExpectation ¶
type TestExpectation struct {
// Success indicates whether the tool call should succeed
Success bool `yaml:"success"`
// ErrorContains checks if error message contains specific text
ErrorContains []string `yaml:"error_contains,omitempty"`
// Contains checks if response contains specific text
Contains []string `yaml:"contains,omitempty"`
// NotContains checks if response does not contain specific text
NotContains []string `yaml:"not_contains,omitempty"`
// JSONPath allows checking specific JSON response fields
JSONPath map[string]interface{} `yaml:"json_path,omitempty"`
// StatusCode for HTTP-based expectations
StatusCode int `yaml:"status_code,omitempty"`
// WaitForState enables polling for state changes with timeout
WaitForState time.Duration `yaml:"wait_for_state,omitempty"`
}
TestExpectation defines what result is expected from a test step
type TestFramework ¶
type TestFramework struct {
Runner TestRunner
Client MCPTestClient
Loader TestScenarioLoader
Reporter TestReporter
InstanceManager MusterInstanceManager
Logger TestLogger
}
TestFramework holds all components needed for testing
func NewTestFrameworkForMode ¶
func NewTestFrameworkForMode(mode ExecutionMode, verbose, debug bool, basePort int, reportPath string, keepTempConfig bool) (*TestFramework, error)
NewTestFrameworkForMode creates a fully configured test framework for the specified execution mode
Execution Modes:
- ExecutionModeCLI: Uses standard stdio output for reporting (compatible with existing behavior)
- ExecutionModeMCPServer: Uses structured reporting that captures data without stdio output to avoid contaminating the MCP protocol stream. Results can be retrieved programmatically.
Note: In MCP server mode, verbose defaults to true and debug output is controlled by the silent logger to prevent stdio contamination.
func NewTestFrameworkWithConfig ¶
func NewTestFrameworkWithConfig(verbose, debug bool, basePort int, reportPath string, keepTempConfig bool) (*TestFramework, error)
NewTestFrameworkWithConfig creates a fully configured test framework with all configuration options
func (*TestFramework) Cleanup ¶
func (tf *TestFramework) Cleanup() error
Cleanup cleans up resources used by the test framework
type TestLogger ¶
type TestLogger interface {
// Debug logs debug-level messages (only shown when debug=true)
Debug(format string, args ...interface{})
// Info logs info-level messages (shown when verbose=true or debug=true)
Info(format string, args ...interface{})
// Error logs error-level messages (always shown)
Error(format string, args ...interface{})
// IsDebugEnabled returns whether debug logging is enabled
IsDebugEnabled() bool
// IsVerboseEnabled returns whether verbose logging is enabled
IsVerboseEnabled() bool
}
TestLogger provides centralized logging for test execution
func NewPrefixedLogger ¶
func NewPrefixedLogger(base TestLogger, prefix string) TestLogger
NewPrefixedLogger creates a new logger that wraps the base logger and adds a prefix to all log messages. The prefix is typically a short unique identifier for the scenario being executed.
func NewSilentLogger ¶
func NewSilentLogger(verbose, debug bool) TestLogger
NewSilentLogger creates a logger that suppresses all output (for MCP server mode)
func NewStdoutLogger ¶
func NewStdoutLogger(verbose, debug bool) TestLogger
NewStdoutLogger creates a logger that outputs to stdout/stderr
type TestReporter ¶
type TestReporter interface {
// ReportStart is called when test execution begins
ReportStart(config TestConfiguration)
// ReportScenarioStart is called when a scenario begins
ReportScenarioStart(scenario TestScenario)
// ReportStepResult is called when a step completes
ReportStepResult(stepResult TestStepResult)
// ReportScenarioResult is called when a scenario completes
ReportScenarioResult(scenarioResult TestScenarioResult)
// ReportSuiteResult is called when all tests complete
ReportSuiteResult(suiteResult TestSuiteResult)
// SetParallelMode enables or disables parallel output buffering
SetParallelMode(parallel bool)
}
TestReporter interface defines how test results are reported
func NewStructuredReporter ¶
func NewStructuredReporter(verbose, debug bool, reportPath string) TestReporter
NewStructuredReporter creates a reporter that captures structured data without stdio output
func NewTestReporter ¶
func NewTestReporter(verbose, debug bool, reportPath string) TestReporter
NewTestReporter creates a new test reporter
type TestResult ¶
type TestResult string
TestResult represents the result of test execution
const ( // ResultPassed indicates the test passed successfully ResultPassed TestResult = "PASSED" // ResultFailed indicates the test failed ResultFailed TestResult = "FAILED" // ResultSkipped indicates the test was skipped ResultSkipped TestResult = "SKIPPED" // ResultError indicates an error occurred during test execution ResultError TestResult = "ERROR" )
type TestRunner ¶
type TestRunner interface {
// Run executes test scenarios according to the configuration
Run(ctx context.Context, config TestConfiguration, scenarios []TestScenario) (*TestSuiteResult, error)
}
TestRunner interface defines the test execution engine
func NewTestRunnerWithLogger ¶
func NewTestRunnerWithLogger(client MCPTestClient, loader TestScenarioLoader, reporter TestReporter, instanceManager MusterInstanceManager, debug bool, logger TestLogger) TestRunner
NewTestRunnerWithLogger creates a new test runner with custom logger
type TestScenario ¶
type TestScenario struct {
// Name is the unique identifier for the scenario
Name string `yaml:"name"`
// Category is the test category (behavioral, integration)
Category TestCategory `yaml:"category"`
// Concept is the core concept being tested
Concept TestConcept `yaml:"concept"`
// Description provides human-readable scenario description
Description string `yaml:"description"`
// Prerequisites define setup requirements
Prerequisites []string `yaml:"prerequisites,omitempty"`
// Steps define the test execution steps
Steps []TestStep `yaml:"steps"`
// Cleanup defines teardown steps
Cleanup []TestStep `yaml:"cleanup,omitempty"`
// Timeout for this specific scenario
Timeout time.Duration `yaml:"timeout,omitempty"`
// Tags for additional categorization
Tags []string `yaml:"tags,omitempty"`
// Skip indicates whether this scenario should be skipped
Skip bool `yaml:"skip,omitempty"`
// PreConfiguration defines muster instance setup
PreConfiguration *MusterPreConfiguration `yaml:"pre_configuration,omitempty"`
}
TestScenario defines a single test scenario
func LoadAndFilterScenarios ¶
func LoadAndFilterScenarios(configPath string, config TestConfiguration, logger TestLogger) ([]TestScenario, error)
LoadAndFilterScenarios provides a unified way to load and filter scenarios
func LoadScenariosForCompletion ¶
func LoadScenariosForCompletion(configPath string) ([]TestScenario, error)
LoadScenariosForCompletion provides a simple way to load scenarios for shell completion This uses minimal logging to avoid interfering with completion output
type TestScenarioLoader ¶
type TestScenarioLoader interface {
// LoadScenarios loads test scenarios from the given path
LoadScenarios(configPath string) ([]TestScenario, error)
// FilterScenarios filters scenarios based on the configuration
FilterScenarios(scenarios []TestScenario, config TestConfiguration) []TestScenario
}
TestScenarioLoader interface defines how test scenarios are loaded
func CreateScenarioLoaderForContext ¶
func CreateScenarioLoaderForContext(debug bool, logger TestLogger) TestScenarioLoader
CreateScenarioLoaderForContext creates a scenario loader appropriate for the given context
func NewTestScenarioLoader ¶
func NewTestScenarioLoader(debug bool) TestScenarioLoader
NewTestScenarioLoader creates a new test scenario loader
func NewTestScenarioLoaderWithLogger ¶
func NewTestScenarioLoaderWithLogger(debug bool, logger TestLogger) TestScenarioLoader
NewTestScenarioLoaderWithLogger creates a new test scenario loader with custom logger
type TestScenarioResult ¶
type TestScenarioResult struct {
// Scenario is the scenario that was executed
Scenario TestScenario `json:"scenario"`
// Result is the overall result of the scenario
Result TestResult `json:"result"`
// StartTime when scenario execution began
StartTime time.Time `json:"start_time"`
// EndTime when scenario execution completed
EndTime time.Time `json:"end_time"`
// Duration of scenario execution
Duration time.Duration `json:"duration"`
// StepResults contains individual step results
StepResults []TestStepResult `json:"step_results"`
// Error message if the scenario failed or had an error
Error string `json:"error,omitempty"`
// Output from scenario execution
Output string `json:"output,omitempty"`
// InstanceLogs contains logs from the muster serve instance
InstanceLogs *InstanceLogs `json:"instance_logs,omitempty"`
}
TestScenarioResult represents the result of a single test scenario
type TestStep ¶
type TestStep struct {
// ID is the step identifier
ID string `yaml:"id"`
// Description explains what the step does
Description string `yaml:"description,omitempty"`
// Tool is the MCP tool to invoke
Tool string `yaml:"tool"`
// Args are the tool arguments as a map
Args map[string]interface{} `yaml:"args"`
// Expected defines the expected outcome
Expected TestExpectation `yaml:"expected"`
// Retry configuration for this step
Retry *RetryConfig `yaml:"retry,omitempty"`
// Timeout for this specific step
Timeout time.Duration `yaml:"timeout,omitempty"`
// AsUser specifies which user session to execute this step as.
// For multi-user testing scenarios. If not set, uses the current user.
AsUser string `yaml:"as_user,omitempty"`
}
TestStep defines a single step within a test scenario
type TestStepResult ¶
type TestStepResult struct {
// Step is the step that was executed
Step TestStep `json:"step"`
// Result is the result of the step
Result TestResult `json:"result"`
// StartTime when step execution began
StartTime time.Time `json:"start_time"`
// EndTime when step execution completed
EndTime time.Time `json:"end_time"`
// Duration of step execution
Duration time.Duration `json:"duration"`
// Response from the MCP tool call
Response interface{} `json:"response,omitempty"`
// Error message if the step failed
Error string `json:"error,omitempty"`
// RetryCount is the number of retries attempted
RetryCount int `json:"retry_count"`
}
TestStepResult represents the result of a single test step
type TestSuiteResult ¶
type TestSuiteResult struct {
// StartTime when test execution began
StartTime time.Time `json:"start_time"`
// EndTime when test execution completed
EndTime time.Time `json:"end_time"`
// Duration of test execution
Duration time.Duration `json:"duration"`
// TotalScenarios is the total number of scenarios executed
TotalScenarios int `json:"total_scenarios"`
// PassedScenarios is the number of scenarios that passed
PassedScenarios int `json:"passed_scenarios"`
// FailedScenarios is the number of scenarios that failed
FailedScenarios int `json:"failed_scenarios"`
// SkippedScenarios is the number of scenarios that were skipped
SkippedScenarios int `json:"skipped_scenarios"`
// ErrorScenarios is the number of scenarios that had errors
ErrorScenarios int `json:"error_scenarios"`
// ScenarioResults contains individual scenario results
ScenarioResults []TestScenarioResult `json:"scenario_results"`
// Configuration used for this test run
Configuration TestConfiguration `json:"configuration"`
}
TestSuiteResult represents the overall result of test suite execution
type TestToolContent ¶
TestToolContent represents content in a test tool result.
type TestToolResult ¶
type TestToolResult struct {
Content []TestToolContent `json:"content"`
IsError bool `json:"isError,omitempty"`
}
TestToolResult wraps a result from a test tool to match MCP response format.
func WrapTestToolResult ¶
func WrapTestToolResult(result interface{}, err error) *TestToolResult
WrapTestToolResult wraps a test tool result in MCP-compatible format.
type TestToolsHandler ¶
type TestToolsHandler struct {
// contains filtered or unexported fields
}
TestToolsHandler handles test-specific tools that operate on mock infrastructure. These tools are NOT exposed through the muster serve MCP server - they are handled directly by the test runner before delegating to the real MCP client.
func NewTestToolsHandler ¶
func NewTestToolsHandler(instanceManager MusterInstanceManager, instance *MusterInstance, debug bool, logger TestLogger) *TestToolsHandler
NewTestToolsHandler creates a new test tools handler.
func (*TestToolsHandler) CloseAllUserClients ¶
func (h *TestToolsHandler) CloseAllUserClients()
CloseAllUserClients closes all user MCP clients except the default one. The default client is managed by the test runner.
func (*TestToolsHandler) GetCurrentClient ¶
func (h *TestToolsHandler) GetCurrentClient() MCPTestClient
GetCurrentClient returns the MCP client for the currently active user.
func (*TestToolsHandler) GetCurrentUserName ¶
func (h *TestToolsHandler) GetCurrentUserName() string
GetCurrentUserName returns the name of the currently active user.
func (*TestToolsHandler) HandleTestTool ¶
func (h *TestToolsHandler) HandleTestTool(ctx context.Context, toolName string, args map[string]interface{}) (interface{}, error)
HandleTestTool executes a test helper tool and returns the result.
func (*TestToolsHandler) HasUser ¶
func (h *TestToolsHandler) HasUser(name string) bool
HasUser returns true if a user session with the given name exists. This provides encapsulated access to check user existence without exposing the internal userClients map.
func (*TestToolsHandler) SetMCPClient ¶
func (h *TestToolsHandler) SetMCPClient(client MCPTestClient)
SetMCPClient sets the MCP client for calling tools in the muster instance. This is used by test_simulate_oauth_callback to call the authenticate tool.
func (*TestToolsHandler) SwitchToUser ¶
func (h *TestToolsHandler) SwitchToUser(name string) bool
SwitchToUser switches the current user context to the specified user. This is used by the test runner to switch user context for as_user steps. Returns false if the user doesn't exist.
type TrustedIssuerConfig ¶
type TrustedIssuerConfig struct {
// ConnectorID is the identifier used in the token exchange request
// to specify which connector to use (maps to audience in RFC 8693)
ConnectorID string `yaml:"connector_id"`
// OAuthServerRef references the mock OAuth server by name whose tokens
// should be accepted for exchange
OAuthServerRef string `yaml:"oauth_server_ref"`
}
TrustedIssuerConfig defines a trusted issuer for RFC 8693 token exchange
type ValidationError ¶
type ValidationError struct {
Type string `json:"type"`
Message string `json:"message"`
Field string `json:"field,omitempty"`
Suggestion string `json:"suggestion,omitempty"`
}
ValidationError represents a validation error
type WorkflowConfig ¶
type WorkflowConfig struct {
// Name is the unique identifier for the workflow
Name string `yaml:"name"`
// Config contains the workflow definition
Config map[string]interface{} `yaml:"config"`
}
WorkflowConfig represents a workflow configuration
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
fixtures
|
|
|
oauth
Package oauth contains test fixtures for OAuth authentication testing.
|
Package oauth contains test fixtures for OAuth authentication testing. |
|
Package mock provides mock MCP server functionality for testing muster components.
|
Package mock provides mock MCP server functionality for testing muster components. |