# 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 ```bash dotnet test test/Koogle.Tests ``` ### Specific Test Categories ```bash # 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: ```bash pwsh test/Koogle.E2E/bin/Debug/net9.0/playwright.ps1 install ``` 2. Start the application: ```bash dotnet run --project src/Koogle.Web ``` 3. Run E2E tests: ```bash 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 ```bash 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: ```csharp [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: ```csharp [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: ```csharp [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 ```csharp var club = TestDataGenerator.CreateClub( name: "My Club", expenseCalculation: ExpenseCalculation.Average); ``` ### 2. Use MockExtensions ```csharp _repositoryMock .SetupGetAllAsync(clubs) .SetupAddAsync(); ``` ### 3. Use FluentAssertions ```csharp 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 |