KoogleApp/test
beo3000 3c7050e172 DemoSeeder.cs:
1. HardDeleteClubDataAsync: Löscht jetzt auch CashBookEntries und BookingCategories (Zeilen 200-201)
  2. ResetDemoClubAsync: Ruft jetzt SeedSystemBookingCategoriesAsync auf (Zeile 183)
  3. Neue Methode SeedSystemBookingCategoriesAsync (Zeilen 578-606): Erstellt die 4 System-Kategorien:
    - Spielstrafe (Income, grün)
    - Mitgliedsbeitrag (Income, blau)
    - Korrekturbuchung (Income, orange)
    - Saldoanpassung (Income, grau)
added tests and fixes

  Bereits vorhanden:
  - ClubService.CreateAsync: Ruft bereits EnsureSystemCategoriesAsync für neue Clubs auf (Zeile 101)

  Die System-Kategorien werden jetzt automatisch:
  - Bei Anlage eines neuen Clubs (via ClubService)
  - Beim Zurücksetzen des Demo-Clubs (via DemoSeeder)
2026-01-04 12:56:15 +01:00
..
Koogle.Tests DemoSeeder.cs: 2026-01-04 12:56:15 +01:00
README.md added test-framework 2025-12-24 14:11:31 +01:00

README.md

Koogle Test Suite

Comprehensive testing infrastructure for the Koogle club management application.

Test Projects

Koogle.Tests

Main test project containing:

  • Unit Tests: Domain entities, services, Fluxor reducers
  • Integration Tests: API endpoints, database operations
  • Component Tests: bUnit tests for Blazor components
  • Performance Tests: Response time and memory allocation tests

Koogle.E2E

End-to-end tests using Playwright:

  • Authentication flow tests
  • User journey tests
  • UI interaction tests

Running Tests

All Tests

dotnet test test/Koogle.Tests

Specific Test Categories

# Unit tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Unit"

# Integration tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Integration"

# Component tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Components"

# Performance tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Performance"

E2E Tests

Before running E2E tests:

  1. Install Playwright browsers:
pwsh test/Koogle.E2E/bin/Debug/net9.0/playwright.ps1 install
  1. Start the application:
dotnet run --project src/Koogle.Web
  1. Run E2E tests:
E2E_BASE_URL=https://localhost:7001 dotnet test test/Koogle.E2E

Environment variables:

  • E2E_BASE_URL: Application URL (default: https://localhost:7001)
  • E2E_HEADLESS: Set to "false" to see browser (default: headless)
  • E2E_SLOWMO: Milliseconds to slow down operations for debugging

Test Coverage

dotnet test test/Koogle.Tests --collect:"XPlat Code Coverage"

Report location: test/Koogle.Tests/TestResults/*/coverage.cobertura.xml

Test Structure

test/
├── Koogle.Tests/
│   ├── Common/                    # Shared test utilities
│   │   ├── TestDataGenerator.cs   # Bogus-based test data
│   │   └── MockExtensions.cs      # Mock setup helpers
│   │
│   ├── Unit/
│   │   ├── Domain/               # Entity tests
│   │   ├── Services/             # Service unit tests
│   │   └── Store/                # Fluxor reducer tests
│   │
│   ├── Integration/              # API & DB integration tests
│   │
│   ├── Components/               # bUnit Blazor tests
│   │
│   └── Performance/              # Performance benchmarks
│
└── Koogle.E2E/
    ├── PageObjectModels/         # Page abstractions
    └── *Tests.cs                 # E2E test files

Test Patterns

AAA Pattern

All tests follow Arrange-Act-Assert:

[Fact]
public async Task GetByIdAsync_ReturnsClub_WhenExists()
{
    // Arrange
    var club = TestDataGenerator.CreateClub();
    _repositoryMock.SetupGetByIdAsync(club.Id, club);

    // Act
    var result = await _sut.GetByIdAsync(club.Id);

    // Assert
    result.Should().NotBeNull();
    result!.Id.Should().Be(club.Id);
}

Theory-Based Testing

For parameterized tests:

[Theory]
[InlineData(ExpenseCalculation.None)]
[InlineData(ExpenseCalculation.Average)]
[InlineData(ExpenseCalculation.Maximum)]
public async Task CreateAsync_HandlesAllExpenseCalculationTypes(ExpenseCalculation calc)
{
    // Test each enum value
}

State Immutability Testing

For Fluxor reducers:

[Fact]
public void Reducers_DoNotMutateOriginalState()
{
    var originalState = ClubState.Initial with { Clubs = [...] };
    var originalCount = originalState.Clubs.Count;

    ClubReducers.OnDeleteClubSuccess(originalState, action);

    originalState.Clubs.Should().HaveCount(originalCount);
}

Writing New Tests

1. Use TestDataGenerator

var club = TestDataGenerator.CreateClub(
    name: "My Club",
    expenseCalculation: ExpenseCalculation.Average);

2. Use MockExtensions

_repositoryMock
    .SetupGetAllAsync(clubs)
    .SetupAddAsync();

3. Use FluentAssertions

result.Should().NotBeNull();
result.Should().HaveCount(3);
result.Should().Contain(x => x.Name == "Club A");

Dependencies

Package Purpose
xUnit Test framework
FluentAssertions Readable assertions
Moq Mocking
bUnit Blazor component testing
Bogus Test data generation
AutoFixture Object creation
Microsoft.AspNetCore.Mvc.Testing Integration testing
Microsoft.Playwright E2E testing
Coverlet Code coverage
RichardSzalay.MockHttp MockHttp for HttpClient