一键导入
testing-patterns
Testing conventions and patterns for this project. Use when writing tests, creating mocks, or understanding the test infrastructure.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Testing conventions and patterns for this project. Use when writing tests, creating mocks, or understanding the test infrastructure.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | testing-patterns |
| description | Testing conventions and patterns for this project. Use when writing tests, creating mocks, or understanding the test infrastructure. |
_test.got.TempDir() for filesystem isolation — no shared state between testsmake test (which uses -race) to verifyThe workspace tests use a mockRunner that implements git.Runner. It records calls and simulates filesystem operations:
type mockRunner struct {
clones []string // URLs passed to BareClone
fetches []string // paths passed to Fetch
worktrees []string // paths passed to AddWorktree
removed []string // paths passed to RemoveWorktree
cloneErr error // inject errors
fetchErr error
addWTErr error
branchExists bool // controls BranchExists return
}
Key behavior: BareClone and AddWorktree create the directories with os.MkdirAll so that subsequent os.Stat checks pass. This simulates git's side effects without actual git.
Creates a fully isolated test environment:
func testService(t *testing.T) (*Service, *mockRunner) {
t.Helper()
dir := t.TempDir()
cfg := &config.Config{
Home: dir,
WorkspacesDir: filepath.Join(dir, "workspaces"),
ReposDir: filepath.Join(dir, "repos"),
AgentsDir: filepath.Join(dir, "agents"),
ConfigFile: filepath.Join(dir, "config.yaml"),
}
if err := cfg.EnsureDirs(); err != nil {
t.Fatal(err)
}
if err := agents.EnsureSharedAgent(cfg.AgentsDir); err != nil {
t.Fatal(err)
}
mock := &mockRunner{}
return &Service{Config: cfg, Git: mock}, mock
}
When adding new fields to Config, update this helper too.
Tests follow a consistent pattern:
func TestOperationName(t *testing.T) {
svc, mock := testService(t)
ctx := context.Background()
// Setup: create workspace with state
st := state.NewState("name", "description", []state.Repo{
{URL: "github.com/org/repo", Branch: "main", Path: "./repo"},
})
if err := svc.Create("ws-id", st); err != nil {
t.Fatal(err)
}
// Act
err := svc.Render(ctx, "ws-id", noop)
if err != nil {
t.Fatalf("Render: %v", err)
}
// Assert
if len(mock.clones) != 1 {
t.Errorf("clones = %d, want 1", len(mock.clones))
}
}
Set error fields on the mock to test failure paths:
mock.cloneErr = errors.New("auth failed")
err := svc.Render(ctx, "ws-id", noop)
if !errors.Is(err, mock.cloneErr) {
t.Errorf("expected wrapped auth error, got %v", err)
}
Many operations should be idempotent. Test by running twice:
// First call
if err := svc.Render(ctx, "ws-id", noop); err != nil {
t.Fatal(err)
}
// Second call — should not error, should skip work
mock.clones = nil
mock.fetches = nil
if err := svc.Render(ctx, "ws-id", noop); err != nil {
t.Fatalf("second render: %v", err)
}
if len(mock.clones) != 0 {
t.Error("second render should not clone")
}
For packages without git dependencies (config, state, agents), test directly without mocks:
func TestFlowConfigRoundTrip(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "config.yaml")
fc := DefaultFlowConfig()
if err := SaveFlowConfig(path, fc); err != nil {
t.Fatalf("Save: %v", err)
}
loaded, err := LoadFlowConfig(path)
if err != nil {
t.Fatalf("Load: %v", err)
}
// assert fields match
}
noop HelperUsed as a progress callback when you don't care about messages:
func noop(_ string) {}
Flow workspace management — commands, state format, rendering, and PRs. Load this skill at the start of every session.
How to create pull requests for this project. Use when opening a PR on GitHub.
How to add new CLI commands to flow. Use when creating a new subcommand, adding flags, or modifying the command tree.
How to create Claude Code skills for this project. Use when adding new skills, creating SKILL.md files, or setting up skill directories.
How to update documentation for this project. Covers updating the root README, creating and updating VHS tape recordings, running gendocs, and the make commands that tie it together.
How to write PRDs for this project. Use when creating a new product requirement document, planning a feature, or adding to docs/prd/.