6.4 KiB
6.4 KiB
測試架構說明
概述
本測試架構採用三層測試策略:單元測試、整合測試、端到端測試。支援 xUnit 測試框架,並整合 Moq 進行 Mock 測試。
測試目錄結構
Tests/
├── README.md # 本文檔 - 測試架構說明
├── Unit/ # 單元測試
│ ├── Services/ # 服務層單元測試
│ ├── Controllers/ # 控制器單元測試
│ └── Repositories/ # Repository 單元測試
├── Integration/ # 整合測試
└── E2E/ # 端到端測試
測試框架與工具
核心測試框架
- xUnit: 主要測試框架
- Moq: Mock 物件框架
- FluentAssertions: 流暢斷言庫
- Microsoft.AspNetCore.Mvc.Testing: ASP.NET Core 測試支援
測試資料庫
- SQLite In-Memory: 用於快速單元測試
- TestContainers: 用於整合測試的容器化資料庫
單元測試規範
命名規範
{TestedMethod}_{Scenario}_{ExpectedResult}
例如:
- GetUserAsync_WithValidId_ReturnsUser()
- AnalyzeSentenceAsync_WithEmptyText_ThrowsArgumentException()
測試結構 (Arrange-Act-Assert)
[Fact]
public async Task GetUserAsync_WithValidId_ReturnsUser()
{
// Arrange
var userId = 1;
var expectedUser = new User { Id = userId, Name = "Test User" };
var mockRepository = new Mock<IUserRepository>();
mockRepository.Setup(r => r.GetByIdAsync(userId))
.ReturnsAsync(expectedUser);
var service = new UserService(mockRepository.Object);
// Act
var result = await service.GetUserAsync(userId);
// Assert
result.Should().NotBeNull();
result.Id.Should().Be(userId);
result.Name.Should().Be("Test User");
}
服務層測試指南
測試重點服務
- GeminiService - AI 服務核心功能
- AuthService - 認證服務
- AnalysisService - 分析服務
- RefactoredHybridCacheService - 快取服務
Mock 策略
- 外部 API 呼叫: 使用 Mock HttpClient
- 資料庫操作: Mock Repository 介面
- 檔案操作: Mock 檔案系統相關服務
整合測試策略
WebApplicationFactory
使用 ASP.NET Core 的 WebApplicationFactory 進行整合測試:
public class IntegrationTestBase : IClassFixture<WebApplicationFactory<Program>>
{
protected readonly WebApplicationFactory<Program> Factory;
protected readonly HttpClient Client;
public IntegrationTestBase(WebApplicationFactory<Program> factory)
{
Factory = factory.WithWebHostBuilder(builder =>
{
builder.UseEnvironment("Testing");
builder.ConfigureServices(services =>
{
// 替換為測試資料庫
services.RemoveAll<DbContextOptions<DramaLingDbContext>>();
services.AddDbContext<DramaLingDbContext>(options =>
options.UseInMemoryDatabase("TestDb"));
});
});
Client = Factory.CreateClient();
}
}
測試資料管理
public class TestDataSeeder
{
public static async Task SeedAsync(DramaLingDbContext context)
{
// 清理現有資料
context.Users.RemoveRange(context.Users);
// 新增測試資料
context.Users.Add(new User { Id = 1, Name = "Test User" });
await context.SaveChangesAsync();
}
}
測試執行命令
執行所有測試
dotnet test
執行特定類別的測試
dotnet test --filter "ClassName=GeminiServiceTests"
執行特定類型的測試
# 只執行單元測試
dotnet test --filter "Category=Unit"
# 只執行整合測試
dotnet test --filter "Category=Integration"
產生測試覆蓋率報告
dotnet test --collect:"XPlat Code Coverage"
測試資料工廠模式
實體建立工廠
public static class TestDataFactory
{
public static User CreateUser(int id = 1, string name = "Test User")
{
return new User
{
Id = id,
Name = name,
Email = $"test{id}@example.com",
CreatedAt = DateTime.UtcNow
};
}
public static Flashcard CreateFlashcard(int id = 1, int userId = 1)
{
return new Flashcard
{
Id = id,
UserId = userId,
Front = "Test Front",
Back = "Test Back",
CreatedAt = DateTime.UtcNow
};
}
}
CI/CD 整合
GitHub Actions 設定範例
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: '8.0.x'
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test --no-build --verbosity normal --collect:"XPlat Code Coverage"
- name: Upload coverage reports
uses: codecov/codecov-action@v1
效能測試指南
基準測試
使用 BenchmarkDotNet 進行效能測試:
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net80)]
public class CachingBenchmarks
{
private ICacheService _cacheService;
[GlobalSetup]
public void Setup()
{
// 初始化快取服務
}
[Benchmark]
public async Task<string> GetFromCache()
{
return await _cacheService.GetAsync<string>("test-key");
}
}
測試最佳實踐
DRY 原則
- 建立共用的測試基類
- 使用測試資料工廠
- 抽取共同的 Setup 邏輯
測試隔離
- 每個測試應該獨立執行
- 避免測試之間的依賴關係
- 使用
IDisposable清理資源
可讀性
- 使用描述性的測試名稱
- 明確的 Arrange-Act-Assert 結構
- 適量的註解說明複雜邏輯
未來擴展計劃
- 測試覆蓋率目標: 達到 80% 以上的程式碼覆蓋率
- 自動化測試: 整合 CI/CD 管道
- 效能回歸測試: 建立效能基準測試
- 安全性測試: 加入安全相關的測試案例
版本: 1.0 建立日期: 2025-09-30 維護者: DramaLing 開發團隊