🎯 refactor: implement comprehensive BDD test suite with modular architecture
Some checks failed
CI/CD Pipeline / Build Docker Cache (push) Successful in 9s
CI/CD Pipeline / CI Pipeline (push) Failing after 3m5s

 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:
2026-04-10 00:00:52 +02:00
parent de22839eb7
commit de2e03519e
22 changed files with 1257 additions and 120 deletions

View File

@@ -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
}
}
}