mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 12:15:42 +00:00
a04d41ce2c
Implement comprehensive eval framework for testing Pulse Assistant: Core components: - Runner: Executes scenarios against live API with SSE stream parsing - Assertions: Reusable checks (tool usage, content, duration, errors) - Scenarios: Multi-step test workflows with configurable assertions Basic scenarios: - QuickSmokeTest: Minimal functionality verification - ReadOnlyInfrastructure: List, logs, status operations - RoutingValidation: Command routing to correct targets - LogTailing: Bounded log commands complete properly - Discovery: Infrastructure discovery capabilities Advanced scenarios: - TroubleshootingScenario: Multi-step investigation workflow - DeepDiveScenario: Thorough single-service investigation - ConfigInspectionScenario: Reading configuration files - ResourceAnalysisScenario: Cross-container resource comparison - MultiNodeScenario: Operations across Proxmox nodes - DockerInDockerScenario: Docker containers inside LXCs - ContextChainScenario: Context retention across turns Usage: go test ./internal/ai/eval -live -run TestQuickSmokeTest
140 lines
3.5 KiB
Go
140 lines
3.5 KiB
Go
package eval
|
|
|
|
import (
|
|
"flag"
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
var runLiveEval = flag.Bool("live", false, "Run live eval against Pulse API (requires running Pulse)")
|
|
|
|
func TestMain(m *testing.M) {
|
|
flag.Parse()
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
// TestQuickSmokeTest runs a minimal smoke test against the live API
|
|
// Run with: go test -v ./internal/ai/eval -run TestQuickSmokeTest -live
|
|
func TestQuickSmokeTest(t *testing.T) {
|
|
if !*runLiveEval {
|
|
t.Skip("Skipping live eval test. Use -live flag to run against live Pulse API")
|
|
}
|
|
|
|
runner := NewRunner(DefaultConfig())
|
|
scenario := QuickSmokeTest()
|
|
|
|
result := runner.RunScenario(scenario)
|
|
runner.PrintSummary(result)
|
|
|
|
if !result.Passed {
|
|
t.Fatalf("Scenario '%s' failed", scenario.Name)
|
|
}
|
|
}
|
|
|
|
// TestReadOnlyInfrastructure runs the full read-only infrastructure scenario
|
|
// Run with: go test -v ./internal/ai/eval -run TestReadOnlyInfrastructure -live
|
|
func TestReadOnlyInfrastructure(t *testing.T) {
|
|
if !*runLiveEval {
|
|
t.Skip("Skipping live eval test. Use -live flag to run against live Pulse API")
|
|
}
|
|
|
|
runner := NewRunner(DefaultConfig())
|
|
scenario := ReadOnlyInfrastructureScenario()
|
|
|
|
result := runner.RunScenario(scenario)
|
|
runner.PrintSummary(result)
|
|
|
|
if !result.Passed {
|
|
t.Fatalf("Scenario '%s' failed", scenario.Name)
|
|
}
|
|
}
|
|
|
|
// TestRoutingValidation runs the routing validation scenario
|
|
// Run with: go test -v ./internal/ai/eval -run TestRoutingValidation -live
|
|
func TestRoutingValidation(t *testing.T) {
|
|
if !*runLiveEval {
|
|
t.Skip("Skipping live eval test. Use -live flag to run against live Pulse API")
|
|
}
|
|
|
|
runner := NewRunner(DefaultConfig())
|
|
scenario := RoutingValidationScenario()
|
|
|
|
result := runner.RunScenario(scenario)
|
|
runner.PrintSummary(result)
|
|
|
|
if !result.Passed {
|
|
t.Fatalf("Scenario '%s' failed", scenario.Name)
|
|
}
|
|
}
|
|
|
|
// TestLogTailing runs the log tailing scenario
|
|
// Run with: go test -v ./internal/ai/eval -run TestLogTailing -live
|
|
func TestLogTailing(t *testing.T) {
|
|
if !*runLiveEval {
|
|
t.Skip("Skipping live eval test. Use -live flag to run against live Pulse API")
|
|
}
|
|
|
|
runner := NewRunner(DefaultConfig())
|
|
scenario := LogTailingScenario()
|
|
|
|
result := runner.RunScenario(scenario)
|
|
runner.PrintSummary(result)
|
|
|
|
if !result.Passed {
|
|
t.Fatalf("Scenario '%s' failed", scenario.Name)
|
|
}
|
|
}
|
|
|
|
// TestDiscovery runs the infrastructure discovery scenario
|
|
// Run with: go test -v ./internal/ai/eval -run TestDiscovery -live
|
|
func TestDiscovery(t *testing.T) {
|
|
if !*runLiveEval {
|
|
t.Skip("Skipping live eval test. Use -live flag to run against live Pulse API")
|
|
}
|
|
|
|
runner := NewRunner(DefaultConfig())
|
|
scenario := DiscoveryScenario()
|
|
|
|
result := runner.RunScenario(scenario)
|
|
runner.PrintSummary(result)
|
|
|
|
if !result.Passed {
|
|
t.Fatalf("Scenario '%s' failed", scenario.Name)
|
|
}
|
|
}
|
|
|
|
// TestAllScenarios runs all defined scenarios
|
|
// Run with: go test -v ./internal/ai/eval -run TestAllScenarios -live
|
|
func TestAllScenarios(t *testing.T) {
|
|
if !*runLiveEval {
|
|
t.Skip("Skipping live eval test. Use -live flag to run against live Pulse API")
|
|
}
|
|
|
|
runner := NewRunner(DefaultConfig())
|
|
|
|
scenarios := []Scenario{
|
|
QuickSmokeTest(),
|
|
ReadOnlyInfrastructureScenario(),
|
|
RoutingValidationScenario(),
|
|
LogTailingScenario(),
|
|
DiscoveryScenario(),
|
|
}
|
|
|
|
allPassed := true
|
|
for _, scenario := range scenarios {
|
|
t.Run(scenario.Name, func(t *testing.T) {
|
|
result := runner.RunScenario(scenario)
|
|
runner.PrintSummary(result)
|
|
|
|
if !result.Passed {
|
|
allPassed = false
|
|
t.Errorf("Scenario '%s' failed", scenario.Name)
|
|
}
|
|
})
|
|
}
|
|
|
|
if !allPassed {
|
|
t.Fatal("One or more scenarios failed")
|
|
}
|
|
}
|