added tests for model_learning_costs
lets see how goo they are
This commit is contained in:
@@ -0,0 +1,510 @@
|
||||
package models
|
||||
|
||||
/*
|
||||
* Database Migration Tests
|
||||
*
|
||||
* This file contains comprehensive tests for database.go migration functions.
|
||||
* Tests cover:
|
||||
* - MigrateStructure and all sub-migration functions
|
||||
* - Database parameter handling (default DB, custom DB, nil handling)
|
||||
* - Table structure verification for all model categories
|
||||
* - Migration idempotency (can be run multiple times safely)
|
||||
* - Integration workflow testing
|
||||
* - Error resilience and edge cases
|
||||
* - Database consistency and relationship verification
|
||||
*/
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func setupDatabaseTestDB(t *testing.T) {
|
||||
database.SetupTestDB()
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests for MigrateStructure function
|
||||
// =============================================================================
|
||||
|
||||
func TestMigrateStructure_DefaultDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := MigrateStructure()
|
||||
|
||||
assert.NoError(t, err, "MigrateStructure should succeed with default database")
|
||||
}
|
||||
|
||||
func TestMigrateStructure_CustomDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
// Use the same database instance for consistency
|
||||
err := MigrateStructure(database.DB)
|
||||
|
||||
assert.NoError(t, err, "MigrateStructure should succeed with custom database")
|
||||
}
|
||||
|
||||
func TestMigrateStructure_NilDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
// Pass nil DB - should fall back to default
|
||||
err := MigrateStructure(nil)
|
||||
|
||||
assert.NoError(t, err, "MigrateStructure should succeed with nil database (fallback to default)")
|
||||
}
|
||||
|
||||
func TestMigrateStructure_VerifyTablesCreated(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := MigrateStructure()
|
||||
require.NoError(t, err, "MigrateStructure should succeed")
|
||||
|
||||
// Verify that key tables exist by checking if we can perform basic operations
|
||||
// Test each migration category
|
||||
|
||||
// Test gsmaster structures
|
||||
var skill Skill
|
||||
err = database.DB.First(&skill).Error
|
||||
// Error is expected if no records exist, but table should exist
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound, "Skills table should exist")
|
||||
|
||||
var spell Spell
|
||||
err = database.DB.First(&spell).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound, "Spells table should exist")
|
||||
|
||||
// Test character structures
|
||||
var char Char
|
||||
err = database.DB.First(&char).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound, "Characters table should exist")
|
||||
|
||||
// Test equipment structures
|
||||
var equipment EqAusruestung
|
||||
err = database.DB.First(&equipment).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound, "Equipment table should exist")
|
||||
|
||||
// Test skills structures
|
||||
var skFertigkeit SkFertigkeit
|
||||
err = database.DB.First(&skFertigkeit).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound, "Skill skills table should exist")
|
||||
|
||||
// Test learning structures
|
||||
var source Source
|
||||
err = database.DB.First(&source).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound, "Learning sources table should exist")
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests for gsMasterMigrateStructure function
|
||||
// =============================================================================
|
||||
|
||||
func TestGsMasterMigrateStructure_DefaultDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := gsMasterMigrateStructure()
|
||||
|
||||
assert.NoError(t, err, "gsMasterMigrateStructure should succeed with default database")
|
||||
}
|
||||
|
||||
func TestGsMasterMigrateStructure_CustomDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := gsMasterMigrateStructure(database.DB)
|
||||
|
||||
assert.NoError(t, err, "gsMasterMigrateStructure should succeed with custom database")
|
||||
}
|
||||
|
||||
func TestGsMasterMigrateStructure_VerifyStructures(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := gsMasterMigrateStructure()
|
||||
require.NoError(t, err, "gsMasterMigrateStructure should succeed")
|
||||
|
||||
// Verify all gsmaster structures can be accessed
|
||||
structures := []interface{}{
|
||||
&Skill{},
|
||||
&WeaponSkill{},
|
||||
&Spell{},
|
||||
&Equipment{},
|
||||
&Weapon{},
|
||||
&Container{},
|
||||
&Transportation{},
|
||||
&Believe{},
|
||||
}
|
||||
|
||||
for _, structure := range structures {
|
||||
err = database.DB.First(structure).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound,
|
||||
"Structure %T table should exist and be accessible", structure)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests for characterMigrateStructure function
|
||||
// =============================================================================
|
||||
|
||||
func TestCharacterMigrateStructure_DefaultDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := characterMigrateStructure()
|
||||
|
||||
assert.NoError(t, err, "characterMigrateStructure should succeed with default database")
|
||||
}
|
||||
|
||||
func TestCharacterMigrateStructure_CustomDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := characterMigrateStructure(database.DB)
|
||||
|
||||
assert.NoError(t, err, "characterMigrateStructure should succeed with custom database")
|
||||
}
|
||||
|
||||
func TestCharacterMigrateStructure_VerifyStructures(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := characterMigrateStructure()
|
||||
require.NoError(t, err, "characterMigrateStructure should succeed")
|
||||
|
||||
// Verify all character structures can be accessed
|
||||
structures := []interface{}{
|
||||
&Char{},
|
||||
&Eigenschaft{},
|
||||
&Lp{},
|
||||
&Ap{},
|
||||
&B{},
|
||||
&Merkmale{},
|
||||
&Erfahrungsschatz{},
|
||||
&Bennies{},
|
||||
&Vermoegen{},
|
||||
&CharacterCreationSession{},
|
||||
}
|
||||
|
||||
for _, structure := range structures {
|
||||
err = database.DB.First(structure).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound,
|
||||
"Structure %T table should exist and be accessible", structure)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests for equipmentMigrateStructure function
|
||||
// =============================================================================
|
||||
|
||||
func TestEquipmentMigrateStructure_DefaultDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := equipmentMigrateStructure()
|
||||
|
||||
assert.NoError(t, err, "equipmentMigrateStructure should succeed with default database")
|
||||
}
|
||||
|
||||
func TestEquipmentMigrateStructure_CustomDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := equipmentMigrateStructure(database.DB)
|
||||
|
||||
assert.NoError(t, err, "equipmentMigrateStructure should succeed with custom database")
|
||||
}
|
||||
|
||||
func TestEquipmentMigrateStructure_VerifyStructures(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := equipmentMigrateStructure()
|
||||
require.NoError(t, err, "equipmentMigrateStructure should succeed")
|
||||
|
||||
// Verify all equipment structures can be accessed
|
||||
structures := []interface{}{
|
||||
&EqAusruestung{},
|
||||
&EqWaffe{},
|
||||
&EqContainer{},
|
||||
}
|
||||
|
||||
for _, structure := range structures {
|
||||
err = database.DB.First(structure).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound,
|
||||
"Structure %T table should exist and be accessible", structure)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests for skillsMigrateStructure function
|
||||
// =============================================================================
|
||||
|
||||
func TestSkillsMigrateStructure_DefaultDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := skillsMigrateStructure()
|
||||
|
||||
assert.NoError(t, err, "skillsMigrateStructure should succeed with default database")
|
||||
}
|
||||
|
||||
func TestSkillsMigrateStructure_CustomDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := skillsMigrateStructure(database.DB)
|
||||
|
||||
assert.NoError(t, err, "skillsMigrateStructure should succeed with custom database")
|
||||
}
|
||||
|
||||
func TestSkillsMigrateStructure_VerifyStructures(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := skillsMigrateStructure()
|
||||
require.NoError(t, err, "skillsMigrateStructure should succeed")
|
||||
|
||||
// Verify all skills structures can be accessed
|
||||
structures := []interface{}{
|
||||
&SkFertigkeit{},
|
||||
&SkWaffenfertigkeit{},
|
||||
&SkZauber{},
|
||||
}
|
||||
|
||||
for _, structure := range structures {
|
||||
err = database.DB.First(structure).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound,
|
||||
"Structure %T table should exist and be accessible", structure)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests for learningMigrateStructure function
|
||||
// =============================================================================
|
||||
|
||||
func TestLearningMigrateStructure_DefaultDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := learningMigrateStructure()
|
||||
|
||||
assert.NoError(t, err, "learningMigrateStructure should succeed with default database")
|
||||
}
|
||||
|
||||
func TestLearningMigrateStructure_CustomDB_Success(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := learningMigrateStructure(database.DB)
|
||||
|
||||
assert.NoError(t, err, "learningMigrateStructure should succeed with custom database")
|
||||
}
|
||||
|
||||
func TestLearningMigrateStructure_VerifyStructures(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := learningMigrateStructure()
|
||||
require.NoError(t, err, "learningMigrateStructure should succeed")
|
||||
|
||||
// Verify all learning structures can be accessed
|
||||
structures := []interface{}{
|
||||
&Source{},
|
||||
&CharacterClass{},
|
||||
&SkillCategory{},
|
||||
&SkillDifficulty{},
|
||||
&SpellSchool{},
|
||||
&ClassCategoryEPCost{},
|
||||
&ClassSpellSchoolEPCost{},
|
||||
&SpellLevelLECost{},
|
||||
&SkillCategoryDifficulty{},
|
||||
&SkillImprovementCost{},
|
||||
&AuditLogEntry{},
|
||||
}
|
||||
|
||||
for _, structure := range structures {
|
||||
err = database.DB.First(structure).Error
|
||||
assert.True(t, err == nil || err == gorm.ErrRecordNotFound,
|
||||
"Structure %T table should exist and be accessible", structure)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Integration tests for complete migration workflow
|
||||
// =============================================================================
|
||||
|
||||
func TestMigrationWorkflow_CompleteFlow(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
// Test that all migration functions can be called in sequence without errors
|
||||
err := gsMasterMigrateStructure()
|
||||
assert.NoError(t, err, "gsMasterMigrateStructure should succeed")
|
||||
|
||||
err = characterMigrateStructure()
|
||||
assert.NoError(t, err, "characterMigrateStructure should succeed")
|
||||
|
||||
err = equipmentMigrateStructure()
|
||||
assert.NoError(t, err, "equipmentMigrateStructure should succeed")
|
||||
|
||||
err = skillsMigrateStructure()
|
||||
assert.NoError(t, err, "skillsMigrateStructure should succeed")
|
||||
|
||||
err = learningMigrateStructure()
|
||||
assert.NoError(t, err, "learningMigrateStructure should succeed")
|
||||
|
||||
// Finally run the complete migration
|
||||
err = MigrateStructure()
|
||||
assert.NoError(t, err, "MigrateStructure should succeed after individual migrations")
|
||||
}
|
||||
|
||||
func TestMigrationWorkflow_Idempotency(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
// Test that running migrations multiple times doesn't cause errors
|
||||
err := MigrateStructure()
|
||||
assert.NoError(t, err, "First MigrateStructure should succeed")
|
||||
|
||||
err = MigrateStructure()
|
||||
assert.NoError(t, err, "Second MigrateStructure should succeed (idempotent)")
|
||||
|
||||
err = MigrateStructure()
|
||||
assert.NoError(t, err, "Third MigrateStructure should succeed (idempotent)")
|
||||
}
|
||||
|
||||
func TestMigrationWorkflow_StructureIntegrity(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
err := MigrateStructure()
|
||||
require.NoError(t, err, "MigrateStructure should succeed")
|
||||
|
||||
// Test that we can create and retrieve basic records for each major category
|
||||
|
||||
// Test gsmaster category with a skill
|
||||
testSkill := &Skill{
|
||||
GameSystem: "midgard",
|
||||
Name: "Test Skill",
|
||||
Category: "Test Category",
|
||||
Difficulty: "normal",
|
||||
Initialwert: 5,
|
||||
Improvable: true,
|
||||
}
|
||||
err = database.DB.Create(testSkill).Error
|
||||
assert.NoError(t, err, "Should be able to create a skill")
|
||||
|
||||
var retrievedSkill Skill
|
||||
err = database.DB.Where("name = ?", "Test Skill").First(&retrievedSkill).Error
|
||||
assert.NoError(t, err, "Should be able to retrieve created skill")
|
||||
assert.Equal(t, "Test Skill", retrievedSkill.Name)
|
||||
|
||||
// Test learning category with a source
|
||||
testSource := &Source{
|
||||
Code: "TEST",
|
||||
Name: "Test Source",
|
||||
GameSystem: "midgard",
|
||||
IsActive: true,
|
||||
}
|
||||
err = database.DB.Create(testSource).Error
|
||||
assert.NoError(t, err, "Should be able to create a source")
|
||||
|
||||
var retrievedSource Source
|
||||
err = database.DB.Where("code = ?", "TEST").First(&retrievedSource).Error
|
||||
assert.NoError(t, err, "Should be able to retrieve created source")
|
||||
assert.Equal(t, "TEST", retrievedSource.Code)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests for database parameter handling
|
||||
// =============================================================================
|
||||
|
||||
func TestMigrationFunctions_ParameterHandling(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
// Test that all functions handle both default and custom DB parameters correctly
|
||||
functions := []struct {
|
||||
name string
|
||||
function func(...*gorm.DB) error
|
||||
}{
|
||||
{"MigrateStructure", MigrateStructure},
|
||||
{"gsMasterMigrateStructure", gsMasterMigrateStructure},
|
||||
{"characterMigrateStructure", characterMigrateStructure},
|
||||
{"equipmentMigrateStructure", equipmentMigrateStructure},
|
||||
{"skillsMigrateStructure", skillsMigrateStructure},
|
||||
{"learningMigrateStructure", learningMigrateStructure},
|
||||
}
|
||||
|
||||
for _, fn := range functions {
|
||||
t.Run(fn.name, func(t *testing.T) {
|
||||
// Test with no parameters (default DB)
|
||||
err := fn.function()
|
||||
assert.NoError(t, err, "%s should work with default DB", fn.name)
|
||||
|
||||
// Test with explicit DB parameter
|
||||
err = fn.function(database.DB)
|
||||
assert.NoError(t, err, "%s should work with explicit DB", fn.name)
|
||||
|
||||
// Test with nil parameter (should fall back to default)
|
||||
err = fn.function(nil)
|
||||
assert.NoError(t, err, "%s should work with nil DB (fallback)", fn.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Error handling and edge case tests
|
||||
// =============================================================================
|
||||
|
||||
func TestMigration_ErrorResilience(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
// Test that migration can handle being called multiple times
|
||||
for i := 0; i < 3; i++ {
|
||||
err := MigrateStructure()
|
||||
assert.NoError(t, err, "Migration attempt %d should succeed", i+1)
|
||||
}
|
||||
|
||||
// Test individual migration functions multiple times
|
||||
functions := []func(...*gorm.DB) error{
|
||||
gsMasterMigrateStructure,
|
||||
characterMigrateStructure,
|
||||
equipmentMigrateStructure,
|
||||
skillsMigrateStructure,
|
||||
learningMigrateStructure,
|
||||
}
|
||||
|
||||
for _, fn := range functions {
|
||||
for i := 0; i < 2; i++ {
|
||||
err := fn()
|
||||
assert.NoError(t, err, "Function should be callable multiple times")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMigration_DatabaseConsistency(t *testing.T) {
|
||||
setupDatabaseTestDB(t)
|
||||
|
||||
// Run complete migration
|
||||
err := MigrateStructure()
|
||||
require.NoError(t, err, "MigrateStructure should succeed")
|
||||
|
||||
// Verify that database state is consistent by checking if we can perform
|
||||
// cross-references between different structure categories
|
||||
|
||||
// Create a character and related data
|
||||
testChar := &Char{
|
||||
BamortBase: BamortBase{
|
||||
Name: "Test Character",
|
||||
},
|
||||
Typ: "Kr",
|
||||
Grad: 1,
|
||||
Public: false,
|
||||
}
|
||||
err = database.DB.Create(testChar).Error
|
||||
assert.NoError(t, err, "Should be able to create character")
|
||||
|
||||
// Create related skill
|
||||
testSkill := &SkFertigkeit{
|
||||
BamortCharTrait: BamortCharTrait{
|
||||
BamortBase: BamortBase{
|
||||
Name: "Test Character Skill",
|
||||
},
|
||||
CharacterID: testChar.ID,
|
||||
},
|
||||
Fertigkeitswert: 10,
|
||||
}
|
||||
err = database.DB.Create(testSkill).Error
|
||||
assert.NoError(t, err, "Should be able to create character skill")
|
||||
|
||||
// Verify relationship by simply checking that the character exists
|
||||
var retrievedChar Char
|
||||
err = database.DB.Where("id = ?", testChar.ID).First(&retrievedChar).Error
|
||||
assert.NoError(t, err, "Character retrieval should work")
|
||||
assert.Equal(t, "Test Character", retrievedChar.Name, "Character name should match")
|
||||
}
|
||||
Reference in New Issue
Block a user