KoogleApp/test/README.md

184 lines
4.5 KiB
Markdown

# 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 |