package testutil import ( "os" "os/exec" "path/filepath" "testing" "skillmgr/pkg/fileutil" ) // SetupTestEnv 设置测试环境 // 返回临时目录路径和清理函数 func SetupTestEnv(t *testing.T) (string, func()) { t.Helper() tmpDir, err := os.MkdirTemp("", "skillmgr-test-*") if err != nil { t.Fatalf("创建临时目录失败: %v", err) } // 设置环境变量 os.Setenv("SKILLMGR_TEST_ROOT", tmpDir) os.Setenv("SKILLMGR_TEST_BASE", tmpDir) cleanup := func() { os.Unsetenv("SKILLMGR_TEST_ROOT") os.Unsetenv("SKILLMGR_TEST_BASE") os.RemoveAll(tmpDir) } return tmpDir, cleanup } // SetupTestRepo 创建一个临时 git 仓库 // 返回仓库路径 func SetupTestRepo(t *testing.T, baseDir string) string { t.Helper() repoDir := filepath.Join(baseDir, "test-repo") if err := os.MkdirAll(repoDir, 0755); err != nil { t.Fatalf("创建仓库目录失败: %v", err) } // 初始化 git 仓库 cmd := exec.Command("git", "init") cmd.Dir = repoDir if output, err := cmd.CombinedOutput(); err != nil { t.Fatalf("git init 失败: %v\n%s", err, output) } // 配置 git user(测试用) configCmds := [][]string{ {"git", "config", "user.email", "test@example.com"}, {"git", "config", "user.name", "Test User"}, } for _, args := range configCmds { cmd := exec.Command(args[0], args[1:]...) cmd.Dir = repoDir if output, err := cmd.CombinedOutput(); err != nil { t.Fatalf("git config 失败: %v\n%s", err, output) } } return repoDir } // CopyFixtureRepo 复制 fixture 仓库并初始化 git func CopyFixtureRepo(t *testing.T, fixtureDir, destDir string) string { t.Helper() repoDir := filepath.Join(destDir, filepath.Base(fixtureDir)) if err := fileutil.CopyDir(fixtureDir, repoDir); err != nil { t.Fatalf("复制 fixture 仓库失败: %v", err) } // 初始化 git 仓库 cmd := exec.Command("git", "init") cmd.Dir = repoDir if output, err := cmd.CombinedOutput(); err != nil { t.Fatalf("git init 失败: %v\n%s", err, output) } // 配置 git user(测试用) configCmds := [][]string{ {"git", "config", "user.email", "test@example.com"}, {"git", "config", "user.name", "Test User"}, } for _, args := range configCmds { cmd := exec.Command(args[0], args[1:]...) cmd.Dir = repoDir if output, err := cmd.CombinedOutput(); err != nil { t.Fatalf("git config 失败: %v\n%s", err, output) } } // 添加并提交 addCmd := exec.Command("git", "add", ".") addCmd.Dir = repoDir if output, err := addCmd.CombinedOutput(); err != nil { t.Fatalf("git add 失败: %v\n%s", err, output) } commitCmd := exec.Command("git", "commit", "-m", "Initial commit") commitCmd.Dir = repoDir if output, err := commitCmd.CombinedOutput(); err != nil { t.Fatalf("git commit 失败: %v\n%s", err, output) } return repoDir } // GetFixturePath 获取 fixture 目录路径 func GetFixturePath(t *testing.T) string { t.Helper() // 尝试几个可能的位置 candidates := []string{ "testdata/fixtures", "../testdata/fixtures", "../../testdata/fixtures", "../../../testdata/fixtures", } for _, candidate := range candidates { if _, err := os.Stat(candidate); err == nil { abs, _ := filepath.Abs(candidate) return abs } } // 从工作目录向上查找 wd, _ := os.Getwd() for { candidate := filepath.Join(wd, "testdata", "fixtures") if _, err := os.Stat(candidate); err == nil { return candidate } parent := filepath.Dir(wd) if parent == wd { break } wd = parent } t.Fatalf("无法找到 fixtures 目录") return "" } // CreateTestSkill 在目录中创建测试 skill func CreateTestSkill(t *testing.T, baseDir, name string) string { t.Helper() skillDir := filepath.Join(baseDir, "skills", name) if err := os.MkdirAll(skillDir, 0755); err != nil { t.Fatalf("创建 skill 目录失败: %v", err) } content := []byte("# " + name + "\n\nTest skill.\n") if err := os.WriteFile(filepath.Join(skillDir, "SKILL.md"), content, 0644); err != nil { t.Fatalf("创建 SKILL.md 失败: %v", err) } return skillDir } // CreateTestCommand 在目录中创建测试命令组 func CreateTestCommand(t *testing.T, baseDir, groupName string, files []string) string { t.Helper() cmdDir := filepath.Join(baseDir, "commands", groupName) if err := os.MkdirAll(cmdDir, 0755); err != nil { t.Fatalf("创建 command 目录失败: %v", err) } for _, file := range files { content := []byte("# " + file + "\n\nTest command.\n") if err := os.WriteFile(filepath.Join(cmdDir, file), content, 0644); err != nil { t.Fatalf("创建 %s 失败: %v", file, err) } } return cmdDir }