🎯 refactor: implement comprehensive BDD test suite with modular architecture
✨ feat: add feature-based test organization per ADR 0024 🐛 fix: resolve compilation errors in suite_feature.go 📝 docs: add comprehensive BDD framework documentation ♻️ refactor: split monolithic tests into modular features 🧪 test: implement synchronization helpers and context management ⚡ perf: add parallel test execution capability 🔧 chore: add feature-specific test scripts and validation 📚 docs: move BDD_TAGS.md to features/ for better organization Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -27,8 +28,37 @@ type Server struct {
|
||||
}
|
||||
|
||||
func NewServer() *Server {
|
||||
// Get feature-specific port from configuration
|
||||
feature := os.Getenv("FEATURE")
|
||||
port := 9191 // Default port
|
||||
|
||||
if feature != "" {
|
||||
// Try to read port from feature-specific config
|
||||
configPath := fmt.Sprintf("features/%s/%s-test-config.yaml", feature, feature)
|
||||
if _, statErr := os.Stat(configPath); statErr == nil {
|
||||
// Read config file to get port
|
||||
content, err := os.ReadFile(configPath)
|
||||
if err == nil {
|
||||
// Simple YAML parsing to extract port
|
||||
lines := strings.Split(string(content), "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "port:") {
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) >= 2 {
|
||||
portStr := strings.TrimSpace(parts[1])
|
||||
if p, err := strconv.Atoi(portStr); err == nil {
|
||||
port = p
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &Server{
|
||||
port: 9191,
|
||||
port: port,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +101,16 @@ func (s *Server) Start() error {
|
||||
|
||||
// monitorConfigFile monitors the test config file for changes and reloads configuration
|
||||
func (s *Server) monitorConfigFile() {
|
||||
testConfigPath := "test-config.yaml"
|
||||
// Get feature-specific config path
|
||||
feature := os.Getenv("FEATURE")
|
||||
var testConfigPath string
|
||||
|
||||
if feature != "" {
|
||||
testConfigPath = fmt.Sprintf("features/%s/%s-test-config.yaml", feature, feature)
|
||||
} else {
|
||||
testConfigPath = "test-config.yaml"
|
||||
}
|
||||
|
||||
lastModTime := time.Time{}
|
||||
fileExists := false
|
||||
|
||||
@@ -151,7 +190,39 @@ func (s *Server) ReloadConfig() error {
|
||||
|
||||
// initDBConnection initializes a direct database connection for cleanup operations
|
||||
func (s *Server) initDBConnection() error {
|
||||
cfg := createTestConfig(s.port)
|
||||
// Get feature-specific configuration
|
||||
feature := os.Getenv("FEATURE")
|
||||
var cfg *config.Config
|
||||
|
||||
if feature != "" {
|
||||
// Try to load feature-specific config
|
||||
configPath := fmt.Sprintf("features/%s/%s-test-config.yaml", feature, feature)
|
||||
if _, err := os.Stat(configPath); err == nil {
|
||||
v := viper.New()
|
||||
v.SetConfigFile(configPath)
|
||||
v.SetConfigType("yaml")
|
||||
|
||||
if readErr := v.ReadInConfig(); readErr == nil {
|
||||
var featureCfg config.Config
|
||||
if unmarshalErr := v.Unmarshal(&featureCfg); unmarshalErr == nil {
|
||||
// Set default values if not configured
|
||||
if featureCfg.Auth.JWTSecret == "" {
|
||||
featureCfg.Auth.JWTSecret = "default-secret-key-please-change-in-production"
|
||||
}
|
||||
if featureCfg.Auth.AdminMasterPassword == "" {
|
||||
featureCfg.Auth.AdminMasterPassword = "admin123"
|
||||
}
|
||||
cfg = &featureCfg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to default config if feature-specific not available
|
||||
if cfg == nil {
|
||||
cfg = createTestConfig(s.port)
|
||||
}
|
||||
|
||||
dsn := fmt.Sprintf(
|
||||
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
|
||||
cfg.Database.Host,
|
||||
@@ -162,10 +233,10 @@ func (s *Server) initDBConnection() error {
|
||||
cfg.Database.SSLMode,
|
||||
)
|
||||
|
||||
var err error
|
||||
s.db, err = sql.Open("postgres", dsn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open database connection: %w", err)
|
||||
var dbErr error
|
||||
s.db, dbErr = sql.Open("postgres", dsn)
|
||||
if dbErr != nil {
|
||||
return fmt.Errorf("failed to open database connection: %w", dbErr)
|
||||
}
|
||||
|
||||
// Test the connection
|
||||
@@ -329,31 +400,48 @@ func (s *Server) GetBaseURL() string {
|
||||
}
|
||||
|
||||
func createTestConfig(port int) *config.Config {
|
||||
// Check if there's a test config file (used by config hot reloading tests)
|
||||
// If it exists, use it. Otherwise, use default config.
|
||||
testConfigPath := "test-config.yaml"
|
||||
if _, err := os.Stat(testConfigPath); err == nil {
|
||||
// Test config file exists, use it
|
||||
v := viper.New()
|
||||
v.SetConfigFile(testConfigPath)
|
||||
v.SetConfigType("yaml")
|
||||
// Check for feature-specific config file first
|
||||
// This supports the new modular BDD test structure
|
||||
feature := os.Getenv("FEATURE")
|
||||
var configPaths []string
|
||||
|
||||
// Read the test config file
|
||||
if err := v.ReadInConfig(); err == nil {
|
||||
var cfg config.Config
|
||||
if err := v.Unmarshal(&cfg); err == nil {
|
||||
// Override server port for testing
|
||||
cfg.Server.Port = port
|
||||
if feature != "" {
|
||||
// Feature-specific config takes precedence
|
||||
configPaths = []string{
|
||||
fmt.Sprintf("features/%s/%s-test-config.yaml", feature, feature),
|
||||
"test-config.yaml", // Fallback to legacy config
|
||||
}
|
||||
} else {
|
||||
// When running all features, use legacy config
|
||||
configPaths = []string{"test-config.yaml"}
|
||||
}
|
||||
|
||||
// Set default auth values if not configured
|
||||
if cfg.Auth.JWTSecret == "" {
|
||||
cfg.Auth.JWTSecret = "default-secret-key-please-change-in-production"
|
||||
// Try each config path in order
|
||||
for _, configPath := range configPaths {
|
||||
if _, err := os.Stat(configPath); err == nil {
|
||||
// Config file exists, use it
|
||||
v := viper.New()
|
||||
v.SetConfigFile(configPath)
|
||||
v.SetConfigType("yaml")
|
||||
|
||||
// Read the config file
|
||||
if err := v.ReadInConfig(); err == nil {
|
||||
var cfg config.Config
|
||||
if err := v.Unmarshal(&cfg); err == nil {
|
||||
// Override server port for testing
|
||||
cfg.Server.Port = port
|
||||
|
||||
// Set default auth values if not configured
|
||||
if cfg.Auth.JWTSecret == "" {
|
||||
cfg.Auth.JWTSecret = "default-secret-key-please-change-in-production"
|
||||
}
|
||||
if cfg.Auth.AdminMasterPassword == "" {
|
||||
cfg.Auth.AdminMasterPassword = "admin123"
|
||||
}
|
||||
|
||||
log.Debug().Str("config", configPath).Msg("Using test config file")
|
||||
return &cfg
|
||||
}
|
||||
if cfg.Auth.AdminMasterPassword == "" {
|
||||
cfg.Auth.AdminMasterPassword = "admin123"
|
||||
}
|
||||
|
||||
return &cfg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user