Files
golang/golang-learning/10-projects/02-todo-list/todo_test.go
2025-08-24 13:01:09 +08:00

383 lines
8.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
todo_test.go - 待办事项测试文件
测试待办事项管理器的各种功能
*/
package main
import (
"fmt"
"testing"
"time"
"./todo"
)
// TestTaskCreation 测试任务创建
func TestTaskCreation(t *testing.T) {
task := todo.NewTask(1, "测试任务")
if task.ID != 1 {
t.Errorf("期望任务ID为1实际为%d", task.ID)
}
if task.Content != "测试任务" {
t.Errorf("期望任务内容为'测试任务',实际为'%s'", task.Content)
}
if task.Completed {
t.Error("新创建的任务不应该是已完成状态")
}
if task.Priority != todo.Medium {
t.Errorf("期望默认优先级为Medium实际为%v", task.Priority)
}
}
// TestTaskCompletion 测试任务完成
func TestTaskCompletion(t *testing.T) {
task := todo.NewTask(1, "测试任务")
// 完成任务
task.Complete()
if !task.Completed {
t.Error("任务应该是已完成状态")
}
if task.CompletedAt == nil {
t.Error("已完成的任务应该有完成时间")
}
// 再次完成(应该没有变化)
oldCompletedAt := *task.CompletedAt
time.Sleep(1 * time.Millisecond)
task.Complete()
if !task.CompletedAt.Equal(oldCompletedAt) {
t.Error("重复完成任务不应该改变完成时间")
}
}
// TestTaskUpdate 测试任务更新
func TestTaskUpdate(t *testing.T) {
task := todo.NewTask(1, "原始内容")
oldUpdatedAt := task.UpdatedAt
time.Sleep(1 * time.Millisecond)
task.Update("新内容")
if task.Content != "新内容" {
t.Errorf("期望任务内容为'新内容',实际为'%s'", task.Content)
}
if !task.UpdatedAt.After(oldUpdatedAt) {
t.Error("更新任务后,更新时间应该改变")
}
}
// TestTaskPriority 测试任务优先级
func TestTaskPriority(t *testing.T) {
task := todo.NewTask(1, "测试任务")
task.SetPriority(todo.High)
if task.Priority != todo.High {
t.Errorf("期望优先级为High实际为%v", task.Priority)
}
}
// TestTaskTags 测试任务标签
func TestTaskTags(t *testing.T) {
task := todo.NewTask(1, "测试任务")
// 添加标签
task.AddTag("工作")
task.AddTag("重要")
if len(task.Tags) != 2 {
t.Errorf("期望标签数量为2实际为%d", len(task.Tags))
}
if !task.HasTag("工作") {
t.Error("任务应该包含'工作'标签")
}
// 添加重复标签
task.AddTag("工作")
if len(task.Tags) != 2 {
t.Error("添加重复标签不应该增加标签数量")
}
// 移除标签
task.RemoveTag("工作")
if task.HasTag("工作") {
t.Error("移除标签后,任务不应该包含该标签")
}
if len(task.Tags) != 1 {
t.Errorf("移除标签后期望标签数量为1实际为%d", len(task.Tags))
}
}
// TestTaskValidation 测试任务验证
func TestTaskValidation(t *testing.T) {
// 有效任务
validTask := todo.NewTask(1, "有效任务")
if err := validTask.Validate(); err != nil {
t.Errorf("有效任务验证失败: %v", err)
}
// 无效ID
invalidTask := &todo.Task{
ID: 0,
Content: "测试",
}
if err := invalidTask.Validate(); err == nil {
t.Error("ID为0的任务应该验证失败")
}
// 空内容
invalidTask = &todo.Task{
ID: 1,
Content: "",
}
if err := invalidTask.Validate(); err == nil {
t.Error("内容为空的任务应该验证失败")
}
}
// TestManager 测试任务管理器
func TestManager(t *testing.T) {
// 使用内存存储进行测试
storage := todo.NewMemoryStorage()
manager := &todo.Manager{}
// 这里需要修改Manager结构以支持注入存储
// 为了简化测试,我们直接测试基本功能
// 创建临时管理器
tempManager, err := todo.NewManager("test_todos.json")
if err != nil {
t.Fatalf("创建管理器失败: %v", err)
}
// 添加任务
task1, err := tempManager.AddTask("任务1")
if err != nil {
t.Errorf("添加任务失败: %v", err)
}
if task1.ID != 1 {
t.Errorf("期望第一个任务ID为1实际为%d", task1.ID)
}
// 添加更多任务
tempManager.AddTask("任务2")
tempManager.AddTask("任务3")
// 获取所有任务
tasks := tempManager.GetTasks()
if len(tasks) != 3 {
t.Errorf("期望任务数量为3实际为%d", len(tasks))
}
// 完成任务
completedTask, err := tempManager.CompleteTask(1)
if err != nil {
t.Errorf("完成任务失败: %v", err)
}
if !completedTask.Completed {
t.Error("任务应该是已完成状态")
}
// 删除任务
deletedTask, err := tempManager.DeleteTask(2)
if err != nil {
t.Errorf("删除任务失败: %v", err)
}
if deletedTask.ID != 2 {
t.Errorf("期望删除的任务ID为2实际为%d", deletedTask.ID)
}
// 检查剩余任务
tasks = tempManager.GetTasks()
if len(tasks) != 2 {
t.Errorf("删除后期望任务数量为2实际为%d", len(tasks))
}
}
// TestManagerSearch 测试搜索功能
func TestManagerSearch(t *testing.T) {
tempManager, err := todo.NewManager("test_search.json")
if err != nil {
t.Fatalf("创建管理器失败: %v", err)
}
// 添加测试任务
tempManager.AddTask("学习Go语言")
tempManager.AddTask("完成项目文档")
tempManager.AddTask("Go语言练习")
// 搜索包含"Go"的任务
results := tempManager.SearchTasks("Go")
if len(results) != 2 {
t.Errorf("期望搜索结果数量为2实际为%d", len(results))
}
// 搜索不存在的关键词
results = tempManager.SearchTasks("Python")
if len(results) != 0 {
t.Errorf("期望搜索结果数量为0实际为%d", len(results))
}
// 空关键词搜索
results = tempManager.SearchTasks("")
if len(results) != 0 {
t.Errorf("空关键词搜索期望结果数量为0实际为%d", len(results))
}
}
// TestManagerStatistics 测试统计功能
func TestManagerStatistics(t *testing.T) {
tempManager, err := todo.NewManager("test_stats.json")
if err != nil {
t.Fatalf("创建管理器失败: %v", err)
}
// 添加测试任务
tempManager.AddTask("任务1")
tempManager.AddTask("任务2")
tempManager.AddTask("任务3")
// 完成一个任务
tempManager.CompleteTask(1)
// 获取统计信息
stats := tempManager.GetStatistics()
if stats.Total != 3 {
t.Errorf("期望总任务数为3实际为%d", stats.Total)
}
if stats.Completed != 1 {
t.Errorf("期望已完成任务数为1实际为%d", stats.Completed)
}
if stats.Pending != 2 {
t.Errorf("期望待完成任务数为2实际为%d", stats.Pending)
}
expectedRate := float64(1) / float64(3) * 100
if stats.CompletionRate != expectedRate {
t.Errorf("期望完成率为%.1f%%,实际为%.1f%%", expectedRate, stats.CompletionRate)
}
}
// TestMemoryStorage 测试内存存储
func TestMemoryStorage(t *testing.T) {
storage := todo.NewMemoryStorage()
// 创建测试任务
tasks := []todo.Task{
*todo.NewTask(1, "任务1"),
*todo.NewTask(2, "任务2"),
}
// 保存任务
err := storage.Save(tasks)
if err != nil {
t.Errorf("保存任务失败: %v", err)
}
// 加载任务
loadedTasks, err := storage.Load()
if err != nil {
t.Errorf("加载任务失败: %v", err)
}
if len(loadedTasks) != 2 {
t.Errorf("期望加载任务数量为2实际为%d", len(loadedTasks))
}
if loadedTasks[0].Content != "任务1" {
t.Errorf("期望第一个任务内容为'任务1',实际为'%s'", loadedTasks[0].Content)
}
}
// TestPriorityString 测试优先级字符串表示
func TestPriorityString(t *testing.T) {
tests := []struct {
priority todo.Priority
expected string
}{
{todo.Low, "低"},
{todo.Medium, "中"},
{todo.High, "高"},
{todo.Urgent, "紧急"},
}
for _, tt := range tests {
t.Run(tt.expected, func(t *testing.T) {
if tt.priority.String() != tt.expected {
t.Errorf("期望优先级字符串为'%s',实际为'%s'", tt.expected, tt.priority.String())
}
})
}
}
// BenchmarkTaskCreation 任务创建基准测试
func BenchmarkTaskCreation(b *testing.B) {
for i := 0; i < b.N; i++ {
todo.NewTask(i, fmt.Sprintf("任务%d", i))
}
}
// BenchmarkManagerAddTask 管理器添加任务基准测试
func BenchmarkManagerAddTask(b *testing.B) {
manager, err := todo.NewManager("bench_test.json")
if err != nil {
b.Fatalf("创建管理器失败: %v", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
manager.AddTask(fmt.Sprintf("基准测试任务%d", i))
}
}
// BenchmarkManagerSearch 搜索基准测试
func BenchmarkManagerSearch(b *testing.B) {
manager, err := todo.NewManager("bench_search.json")
if err != nil {
b.Fatalf("创建管理器失败: %v", err)
}
// 添加测试数据
for i := 0; i < 1000; i++ {
manager.AddTask(fmt.Sprintf("测试任务%d", i))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
manager.SearchTasks("测试")
}
}
// ExampleTask_String 任务字符串表示示例
func ExampleTask_String() {
task := todo.NewTask(1, "学习Go语言")
fmt.Println(task.String())
// Output: [1] ⏳ 学习Go语言 (优先级: 中)
}
// ExampleManager_AddTask 添加任务示例
func ExampleManager_AddTask() {
manager, _ := todo.NewManager("example.json")
task, _ := manager.AddTask("完成项目文档")
fmt.Printf("任务已添加: %s (ID: %d)", task.Content, task.ID)
// Output: 任务已添加: 完成项目文档 (ID: 1)
}