Set Test environment in tests

This commit is contained in:
2025-08-10 21:01:18 +02:00
parent 1880051165
commit 84158683cd
10 changed files with 346 additions and 18 deletions
+7 -1
View File
@@ -26,7 +26,13 @@ LOG_LEVEL=DEBUG
# ====================== # ======================
# Datenbank Konfiguration # Datenbank Konfiguration
# ====================== # ======================
# DATABASE_URL=postgresql://user:password@localhost:5432/bamort_db # Unterstützte Typen: mysql, sqlite
DATABASE_TYPE=mysql
# Beispiel-URLs für verschiedene Datenbank-Typen:
# MySQL: DATABASE_URL=user:password@tcp(localhost:3306)/database?charset=utf8mb4&parseTime=True&loc=Local
# PostgreSQL: DATABASE_URL=postgresql://user:password@localhost:5432/database
# SQLite: DATABASE_URL=./database.db
DATABASE_URL=
# ====================== # ======================
# Beispiel-Konfigurationen # Beispiel-Konfigurationen
+3 -1
View File
@@ -23,4 +23,6 @@ LOG_LEVEL=INFO
# ====================== # ======================
# Datenbank Konfiguration # Datenbank Konfiguration
# ====================== # ======================
# DATABASE_URL=postgresql://user:password@prod-host:5432/bamort_prod_db # Unterstützte Typen: mysql, sqlite
DATABASE_TYPE=mysql
# DATABASE_URL=user:password@tcp(prod-host:3306)/bamort_prod?charset=utf8mb4&parseTime=True&loc=Local
+152
View File
@@ -0,0 +1,152 @@
# Test Environment Configuration
## Überblick
Alle Tests in diesem Projekt sind so konfiguriert, dass sie `ENVIRONMENT=test` verwenden, um sicherzustellen, dass:
1. Die richtige Datenbank-Konfiguration verwendet wird (Test-DB statt Production-DB)
2. Logger-Ausgaben reduziert sind
3. Tests isoliert von der Produktionsumgebung laufen
## Test-Umgebung einrichten
### Option 1: Lokale setupTestEnvironment Funktion (empfohlen)
Jeder Test sollte eine lokale `setupTestEnvironment` Funktion verwenden:
```go
package mypackage
import (
"os"
"testing"
)
// setupTestEnvironment setzt ENVIRONMENT=test für Tests
func setupTestEnvironment(t *testing.T) {
original := os.Getenv("ENVIRONMENT")
os.Setenv("ENVIRONMENT", "test")
t.Cleanup(func() {
if original != "" {
os.Setenv("ENVIRONMENT", original)
} else {
os.Unsetenv("ENVIRONMENT")
}
})
}
func TestMyFunction(t *testing.T) {
setupTestEnvironment(t)
// Ihr Test-Code hier...
}
```
### Option 2: testutils Package (für komplexere Setups)
Für komplexere Test-Setups verwenden Sie das `testutils` Package:
```go
package mypackage
import (
"bamort/testutils"
"testing"
)
func TestMyFunction(t *testing.T) {
testutils.SetupTestEnvironment(t)
// Oder für spezifische Konfiguration:
testutils.SetupTestEnvironmentWithConfig(t, map[string]string{
"DEBUG": "false",
"LOG_LEVEL": "ERROR",
})
// Ihr Test-Code hier...
}
```
## Aktualisierte Test-Dateien
Folgende Test-Dateien wurden bereits aktualisiert:
-`config/config_test.go` - Alle Tests setzen ENVIRONMENT=test
-`logger/logger_test.go` - Alle Tests setzen ENVIRONMENT=test
-`character/character_test.go` - setupTestEnvironment hinzugefügt
-`character/handlers_test.go` - Test-Umgebung konfiguriert
## Database-Tests
Die `database.ConnectDatabase()` Funktion erkennt automatisch `ENVIRONMENT=test` und verwendet die Test-Datenbank:
```go
func ConnectDatabase() *gorm.DB {
cfg := config.LoadConfig()
if cfg.Environment == "test" {
logger.Debug("Test-Umgebung erkannt, verwende Test-Datenbank")
SetupTestDB()
} else {
logger.Debug("Verwende konfigurierte Datenbank (%s)", cfg.DatabaseType)
return ConnectDatabaseOrig()
}
return DB
}
```
## Best Practices
1. **Immer setupTestEnvironment() aufrufen**: Jeder Test sollte die Umgebung konfigurieren
2. **Cleanup automatisch**: Verwenden Sie `t.Cleanup()` um ursprüngliche Werte wiederherzustellen
3. **Test-Isolation**: Tests sollten sich nicht gegenseitig beeinflussen
4. **Keine Produktionsdaten**: Tests verwenden immer Test-Datenbank
## Verifikation
Um zu prüfen, ob alle Tests korrekt konfiguriert sind:
```bash
# Script ausführen
./verify_test_environment.sh
# Einzelne Packages testen
go test ./config -v
go test ./logger -v
go test ./character -v
```
## Migration bestehender Tests
Für bestehende Tests, die noch nicht aktualisiert wurden:
1. Import für `os` hinzufügen
2. `setupTestEnvironment` Funktion hinzufügen
3. `setupTestEnvironment(t)` am Anfang jeder Test-Funktion aufrufen
Beispiel:
```go
// Vor der Migration
func TestMyFunction(t *testing.T) {
// Test-Code...
}
// Nach der Migration
func TestMyFunction(t *testing.T) {
setupTestEnvironment(t)
// Test-Code...
}
```
## Troubleshooting
**Problem**: Test verwendet Produktions-Datenbank
**Lösung**: `setupTestEnvironment(t)` am Anfang des Tests aufrufen
**Problem**: Umgebungsvariablen beeinflussen sich zwischen Tests
**Lösung**: `t.Cleanup()` verwenden für automatisches Aufräumen
**Problem**: Import-Zyklen bei testutils
**Lösung**: Lokale `setupTestEnvironment` Funktion in jedem Package verwenden
+14
View File
@@ -12,6 +12,19 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
// setupTestEnvironment setzt ENVIRONMENT=test für Tests
func setupTestEnvironment(t *testing.T) {
original := os.Getenv("ENVIRONMENT")
os.Setenv("ENVIRONMENT", "test")
t.Cleanup(func() {
if original != "" {
os.Setenv("ENVIRONMENT", original)
} else {
os.Unsetenv("ENVIRONMENT")
}
})
}
// ReadImageAsBase64 reads an image file and returns it as a Base64 string // ReadImageAsBase64 reads an image file and returns it as a Base64 string
// with the prefix "data:mimeType;base64," // with the prefix "data:mimeType;base64,"
func ReadImageAsBase64(filePath string) (string, error) { func ReadImageAsBase64(filePath string) (string, error) {
@@ -746,6 +759,7 @@ func charTests(t *testing.T, char *models.Char) {
} }
func TestCreateChar(t *testing.T) { func TestCreateChar(t *testing.T) {
setupTestEnvironment(t)
database.SetupTestDB() database.SetupTestDB()
err := models.MigrateStructure() err := models.MigrateStructure()
+11
View File
@@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os"
"testing" "testing"
"bamort/database" "bamort/database"
@@ -15,6 +16,16 @@ import (
) )
func TestImproveSkillHandler(t *testing.T) { func TestImproveSkillHandler(t *testing.T) {
// Setup test environment
original := os.Getenv("ENVIRONMENT")
os.Setenv("ENVIRONMENT", "test")
t.Cleanup(func() {
if original != "" {
os.Setenv("ENVIRONMENT", original)
} else {
os.Unsetenv("ENVIRONMENT")
}
})
// Setup test database // Setup test database
database.SetupTestDB(true, true) database.SetupTestDB(true, true)
defer database.ResetTestDB() defer database.ResetTestDB()
+5
View File
@@ -14,6 +14,7 @@ type Config struct {
// Database Konfiguration // Database Konfiguration
DatabaseURL string DatabaseURL string
DatabaseType string
// Logging Konfiguration // Logging Konfiguration
DebugMode bool DebugMode bool
@@ -28,6 +29,7 @@ func defaultConfig() *Config {
return &Config{ return &Config{
ServerPort: "8180", ServerPort: "8180",
DatabaseURL: "", DatabaseURL: "",
DatabaseType: "mysql",
DebugMode: false, DebugMode: false,
LogLevel: "INFO", LogLevel: "INFO",
Environment: "production", Environment: "production",
@@ -53,6 +55,9 @@ func LoadConfig() *Config {
if dbURL := os.Getenv("DATABASE_URL"); dbURL != "" { if dbURL := os.Getenv("DATABASE_URL"); dbURL != "" {
config.DatabaseURL = dbURL config.DatabaseURL = dbURL
} }
if dbType := os.Getenv("DATABASE_TYPE"); dbType != "" {
config.DatabaseType = strings.ToLower(dbType)
}
// Debug Mode // Debug Mode
if debug := os.Getenv("DEBUG"); debug != "" { if debug := os.Getenv("DEBUG"); debug != "" {
+18
View File
@@ -5,7 +5,21 @@ import (
"testing" "testing"
) )
// setupTestEnvironment setzt ENVIRONMENT=test für Tests und stellt es nach dem Test wieder her
func setupTestEnvironment(t *testing.T) {
original := os.Getenv("ENVIRONMENT")
os.Setenv("ENVIRONMENT", "test")
t.Cleanup(func() {
if original != "" {
os.Setenv("ENVIRONMENT", original)
} else {
os.Unsetenv("ENVIRONMENT")
}
})
}
func TestLoadEnvFile(t *testing.T) { func TestLoadEnvFile(t *testing.T) {
setupTestEnvironment(t)
// Test-Datei erstellen // Test-Datei erstellen
envContent := `# Test .env file envContent := `# Test .env file
DEBUG=true DEBUG=true
@@ -97,6 +111,8 @@ QUOTED_VALUE='single quotes'
} }
func TestEnvVariablesPrecedence(t *testing.T) { func TestEnvVariablesPrecedence(t *testing.T) {
setupTestEnvironment(t)
// Test, dass bereits gesetzte Umgebungsvariablen Vorrang haben // Test, dass bereits gesetzte Umgebungsvariablen Vorrang haben
envContent := `DEBUG=false envContent := `DEBUG=false
LOG_LEVEL=ERROR` LOG_LEVEL=ERROR`
@@ -130,6 +146,8 @@ LOG_LEVEL=ERROR`
} }
func TestLoadConfigWithEnvFile(t *testing.T) { func TestLoadConfigWithEnvFile(t *testing.T) {
setupTestEnvironment(t)
// Test-Konfiguration mit .env-Datei // Test-Konfiguration mit .env-Datei
envContent := `ENVIRONMENT=development envContent := `ENVIRONMENT=development
DEBUG=true DEBUG=true
+45 -8
View File
@@ -1,6 +1,8 @@
package database package database
import ( import (
"bamort/config"
"bamort/logger"
"database/sql/driver" "database/sql/driver"
"encoding/json" "encoding/json"
"errors" "errors"
@@ -10,6 +12,7 @@ import (
"log" "log"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -37,22 +40,56 @@ var (
) )
func ConnectDatabase() *gorm.DB { func ConnectDatabase() *gorm.DB {
// Konfiguration laden um zu entscheiden, welche Datenbank verwendet werden soll
cfg := config.LoadConfig()
// In Test-Umgebung verwende Test-DB, sonst die konfigurierte Datenbank
if cfg.Environment == "test" {
logger.Debug("Test-Umgebung erkannt, verwende Test-Datenbank")
SetupTestDB() SetupTestDB()
/* } else {
db, err := gorm.Open(sqlite.Open(PreparedTestDB), &gorm.Config{}) logger.Debug("Verwende konfigurierte Datenbank (%s)", cfg.DatabaseType)
if err != nil { return ConnectDatabaseOrig()
log.Fatal("Failed to connect to database:", err)
} }
DB = db
*/
return DB return DB
} }
func ConnectDatabaseOrig() *gorm.DB { func ConnectDatabaseOrig() *gorm.DB {
dsn := "bamort:bG4)efozrc@tcp(192.168.0.5:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local" // Konfiguration laden
database, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) cfg := config.LoadConfig()
logger.Debug("Datenbank-Konfiguration geladen: Type=%s, URL=%s", cfg.DatabaseType, cfg.DatabaseURL)
// Falls keine URL konfiguriert ist, verwende Standard-MySQL-Konfiguration als Fallback
dbURL := cfg.DatabaseURL
if dbURL == "" {
dbURL = "bamort:bG4)efozrc@tcp(192.168.0.5:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local"
logger.Warn("Keine DATABASE_URL konfiguriert, verwende Standard-MySQL-Konfiguration")
cfg.DatabaseType = "mysql"
}
var database *gorm.DB
var err error
// Datenbanktyp-spezifische Verbindung
switch cfg.DatabaseType {
case "mysql":
logger.Debug("Verbinde mit MySQL-Datenbank...")
database, err = gorm.Open(mysql.Open(dbURL), &gorm.Config{})
case "sqlite":
logger.Debug("Verbinde mit SQLite-Datenbank...")
database, err = gorm.Open(sqlite.Open(dbURL), &gorm.Config{})
default:
logger.Error("Nicht unterstützter Datenbanktyp: %s. Verwende MySQL als Fallback.", cfg.DatabaseType)
database, err = gorm.Open(mysql.Open(dbURL), &gorm.Config{})
}
if err != nil { if err != nil {
logger.Error("Fehler beim Verbinden mit der Datenbank (%s): %s", cfg.DatabaseType, err.Error())
log.Fatal("Failed to connect to database:", err) log.Fatal("Failed to connect to database:", err)
} }
logger.Info("Erfolgreich mit %s-Datenbank verbunden", cfg.DatabaseType)
DB = database DB = database
return DB return DB
} }
+22
View File
@@ -5,7 +5,21 @@ import (
"testing" "testing"
) )
// setupTestEnvironment setzt ENVIRONMENT=test für Tests
func setupTestEnvironment(t *testing.T) {
original := os.Getenv("ENVIRONMENT")
os.Setenv("ENVIRONMENT", "test")
t.Cleanup(func() {
if original != "" {
os.Setenv("ENVIRONMENT", original)
} else {
os.Unsetenv("ENVIRONMENT")
}
})
}
func TestLogLevels(t *testing.T) { func TestLogLevels(t *testing.T) {
setupTestEnvironment(t)
// Test String-Representation der Log-Levels // Test String-Representation der Log-Levels
tests := []struct { tests := []struct {
level LogLevel level LogLevel
@@ -25,6 +39,8 @@ func TestLogLevels(t *testing.T) {
} }
func TestDebugModeFromEnv(t *testing.T) { func TestDebugModeFromEnv(t *testing.T) {
setupTestEnvironment(t)
// Test verschiedene Umgebungsvariablen-Werte // Test verschiedene Umgebungsvariablen-Werte
tests := []struct { tests := []struct {
envValue string envValue string
@@ -55,6 +71,8 @@ func TestDebugModeFromEnv(t *testing.T) {
} }
func TestMinLogLevelFromEnv(t *testing.T) { func TestMinLogLevelFromEnv(t *testing.T) {
setupTestEnvironment(t)
// Test verschiedene LOG_LEVEL Werte // Test verschiedene LOG_LEVEL Werte
tests := []struct { tests := []struct {
envValue string envValue string
@@ -97,6 +115,8 @@ func TestMinLogLevelFromEnv(t *testing.T) {
} }
func TestSetDebugMode(t *testing.T) { func TestSetDebugMode(t *testing.T) {
setupTestEnvironment(t)
// Test Debug-Modus aktivieren // Test Debug-Modus aktivieren
SetDebugMode(true) SetDebugMode(true)
if !IsDebugEnabled() { if !IsDebugEnabled() {
@@ -111,6 +131,8 @@ func TestSetDebugMode(t *testing.T) {
} }
func TestSetMinLogLevel(t *testing.T) { func TestSetMinLogLevel(t *testing.T) {
setupTestEnvironment(t)
// Test verschiedene Log-Level setzen // Test verschiedene Log-Level setzen
levels := []LogLevel{DEBUG, INFO, WARN, ERROR} levels := []LogLevel{DEBUG, INFO, WARN, ERROR}
+61
View File
@@ -0,0 +1,61 @@
package testutils
import (
"os"
"testing"
)
// SetupTestEnvironment konfiguriert die Umgebung für Tests
// Diese Funktion setzt ENVIRONMENT=test und stellt sicher, dass nach dem Test
// die ursprüngliche Umgebung wiederhergestellt wird
func SetupTestEnvironment(t *testing.T) {
// Sicherstellen, dass ENVIRONMENT auf "test" gesetzt ist
originalEnv := os.Getenv("ENVIRONMENT")
os.Setenv("ENVIRONMENT", "test")
// Cleanup-Funktion registrieren
t.Cleanup(func() {
if originalEnv != "" {
os.Setenv("ENVIRONMENT", originalEnv)
} else {
os.Unsetenv("ENVIRONMENT")
}
})
}
// SetupTestEnvironmentWithConfig konfiguriert die Test-Umgebung mit spezifischen Werten
func SetupTestEnvironmentWithConfig(t *testing.T, envVars map[string]string) {
// Ursprüngliche Werte sichern
originalVars := make(map[string]string)
for key := range envVars {
originalVars[key] = os.Getenv(key)
}
// Sicherstellen, dass ENVIRONMENT auf "test" gesetzt ist
envVars["ENVIRONMENT"] = "test"
// Test-Umgebungsvariablen setzen
for key, value := range envVars {
os.Setenv(key, value)
}
// Cleanup-Funktion registrieren
t.Cleanup(func() {
for key, originalValue := range originalVars {
if originalValue != "" {
os.Setenv(key, originalValue)
} else {
os.Unsetenv(key)
}
}
})
}
// EnsureTestEnvironment ist eine einfache Prüfung, ob die Test-Umgebung korrekt ist
// Kann in Tests verwendet werden um sicherzustellen, dass ENVIRONMENT=test gesetzt ist
func EnsureTestEnvironment(t *testing.T) {
if os.Getenv("ENVIRONMENT") != "test" {
t.Errorf("ENVIRONMENT sollte 'test' sein, ist aber '%s'. Vergessen Sie SetupTestEnvironment() aufzurufen?",
os.Getenv("ENVIRONMENT"))
}
}