Skip to content
Back to skills

Concurrent Test Safety

ASecurity

Audits tests for concurrency safety — race conditions, shared mock state, cleanup ordering. Use when writing tests that involve goroutines, async operations, or shared mutable state.

  • 85 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 28, 2026
ai-agentsgo

Security analysis

A100/100

Scanned May 28, 2026

npx -y skills add ash1794/vibe-engineering --skill vibe-concurrent-test-safety --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Concurrent Test Safety?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Concurrent Test Safety
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ash1794-concurrent-test-safety/badge)](https://www.skillsdirectory.com/skills/ash1794-concurrent-test-safety)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: vibe-concurrent-test-safety
description: Audits tests for concurrency safety — race conditions, shared mock state, cleanup ordering. Use when writing tests that involve goroutines, async operations, or shared mutable state.
user-invocable: true
---

# vibe-concurrent-test-safety

Flaky tests are almost always concurrency bugs in the test, not the code.

## When to Use This Skill

- Writing tests that launch goroutines or async operations
- Tests use shared mock objects accessed by multiple goroutines
- Tests that fail intermittently ("flaky")
- After adding `-race` flag and getting failures
- Tests that involve daemon/server startup and shutdown

## When NOT to Use This Skill

- Purely synchronous tests with no concurrency
- Tests that are already race-free (verified with `-race` flag)
- Simple mock-based tests with single-threaded access

## Common Concurrency Bugs in Tests

### 1. Direct Mock State Access
```go
// BAD: Race condition -- mock.Requests accessed while goroutine writes
go daemon.Run(ctx)
time.Sleep(100 * time.Millisecond)
assert.Equal(t, 3, len(mock.Requests)) // RACE!

// GOOD: Thread-safe accessor
go daemon.Run(ctx)
time.Sleep(100 * time.Millisecond)
assert.Equal(t, 3, mock.RequestCount()) // Safe
```

### 2. Missing Context Cancellation Before Cleanup
```go
// BAD: Close bus while daemon goroutine still using it
go daemon.Run(ctx)
defer bus.Close() // daemon may still be writing!

// GOOD: Cancel context first, wait, then cleanup
go daemon.Run(ctx)
defer func() {
    cancel()          // Signal daemon to stop
    <-daemon.Done()   // Wait for it
    bus.Close()        // Now safe
}()
```

### 3. Assertions on Timing
```go
// BAD: Relies on timing
go startServer()
time.Sleep(50 * time.Millisecond) // May not be enough
resp := callServer()

// GOOD: Wait for readiness
go startServer()
waitForReady(server) // Poll or use channel
resp := callServer()
```

## Audit Checklist

- [ ] No direct access to shared mock fields (use accessors)
- [ ] Context cancelled before resource cleanup
- [ ] Goroutines joined before test ends (`<-done` or `wg.Wait()`)
- [ ] No `time.Sleep` for synchronization (use channels, waitgroups, or polling)
- [ ] Assertions use `Eventually` or polling for async results
- [ ] Test passes with `-race` flag
- [ ] Test passes when run 100 times (`-count=100`)

## Output Format

### Concurrent Test Safety Audit: [Test File]

**Issues Found**: X

| # | Issue | Line | Fix |
|---|-------|------|-----|
| 1 | Direct mock access | :42 | Use mock.RequestCount() |
| 2 | Missing cancel before Close | :15 | Add cancel() before defer |

### Suggested Fixes
[Code snippets for each fix]

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.