aiwg
Version:
Cognitive architecture for AI-augmented software development with structured memory, ensemble validation, and closed-loop correction. FAIR-aligned artifacts, 84% cost reduction via human-in-the-loop, standards adopted by 100+ organizations.
314 lines (253 loc) • 7.74 kB
Markdown
---
name: flaky-fix
description: Suggest and apply fixes for flaky tests based on detected patterns. Use after flaky-detect identifies unreliable tests that need repair.
version: 1.0.0
---
Analyze flaky test patterns and suggest or auto-apply fixes. Based on FlakyFix research showing LLMs can automatically repair flaky tests with targeted prompts.
| Finding | Source | Reference |
|---------|--------|-----------|
| LLM Auto-repair | FlakyFix (2023) | [arXiv:2307.00012](https://arxiv.org/html/2307.00012v4) - 70%+ success rate |
| Flaky Taxonomy | Google (2016) | [Flaky Tests Study](https://testing.googleblog.com/2016/05/flaky-tests-at-google-and-how-we.html) |
| Pattern-based Fixes | FlaKat (2024) | [arXiv:2403.01003](https://arxiv.org/abs/2403.01003) |
- After `flaky-detect` identifies flaky tests
- User asks to "fix flaky test" or "make test reliable"
- CI is failing intermittently on specific tests
- Test marked as flaky needs repair
| Natural Language | Action |
|------------------|--------|
| "Fix this flaky test" | Analyze and suggest fix |
| "Make this test reliable" | Apply deterministic patterns |
| "Why is this test flaky?" | Root cause analysis + fix |
| "Auto-fix flaky tests" | Batch fix safe patterns |
| "Remove timing dependency" | Specific timing fix |
```typescript
// FLAKY: Time-dependent
it('should expire after 1 hour', () => {
const token = createToken();
expect(token.expiresAt).toBeGreaterThan(Date.now());
});
```
```typescript
// FIXED: Mocked time
it('should expire after 1 hour', () => {
const fixedTime = new Date('2024-01-01T00:00:00Z');
vi.setSystemTime(fixedTime);
const token = createToken();
expect(token.expiresAt).toBe(fixedTime.getTime() + 3600000);
vi.useRealTimers();
});
```
```typescript
// FLAKY: Arbitrary delay
it('should complete async operation', async () => {
startAsyncOperation();
await sleep(100); // Race condition!
expect(result).toBeDefined();
});
```
```typescript
// FIXED: Wait for actual completion
it('should complete async operation', async () => {
const result = await startAsyncOperation();
expect(result).toBeDefined();
});
// Or use waitFor for DOM
it('should show loading state', async () => {
render(<Component />);
await waitFor(() => {
expect(screen.getByText('Loaded')).toBeInTheDocument();
});
});
```
```typescript
// FLAKY: Promise not awaited
it('should fetch data', () => {
const promise = fetchData();
promise.then(data => {
expect(data).toBeDefined(); // May not run before test ends
});
});
```
```typescript
// FIXED: Awaited promise
it('should fetch data', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});
```
```typescript
// FLAKY: Order not guaranteed
it('should process items', async () => {
const results = [];
items.forEach(async item => {
results.push(await process(item));
});
expect(results.length).toBe(3); // Race!
});
```
```typescript
// FIXED: Guaranteed order
it('should process items', async () => {
const results = await Promise.all(
items.map(item => process(item))
);
expect(results.length).toBe(3);
});
```
```typescript
// FLAKY: Shared state between tests
let counter = 0;
it('should increment', () => {
counter++;
expect(counter).toBe(1); // Fails if other test runs first
});
```
```typescript
// FIXED: Isolated state
describe('counter', () => {
let counter;
beforeEach(() => {
counter = 0; // Fresh state each test
});
it('should increment', () => {
counter++;
expect(counter).toBe(1);
});
});
```
```typescript
// FLAKY: Random ID
it('should create user with ID', () => {
const user = createUser();
expect(user.id).toBe('expected-id'); // Random!
});
```
```typescript
// FIXED: Deterministic ID
it('should create user with ID', () => {
vi.mock('uuid', () => ({
v4: () => 'test-uuid-1234'
}));
const user = createUser();
expect(user.id).toBe('test-uuid-1234');
});
```
```typescript
// FLAKY: Real network
it('should fetch from API', async () => {
const data = await fetch('https://api.example.com/data');
expect(data).toBeDefined(); // Network failures!
});
```
```typescript
// FIXED: Mocked network
it('should fetch from API', async () => {
vi.mock('node-fetch', () => ({
default: vi.fn().mockResolvedValue({
json: () => ({ success: true })
})
}));
const data = await fetchFromApi();
expect(data.success).toBe(true);
});
```
| Pattern | Detection | Fix |
|---------|-----------|-----|
| `Date.now()` in assertion | Regex | Wrap with `vi.setSystemTime()` |
| Missing `await` on async | AST analysis | Add `await` keyword |
| `setTimeout` in test | Regex | Replace with `vi.advanceTimersByTime()` |
| `Math.random()` | Regex | Mock with deterministic value |
| Pattern | Why Review Needed |
|---------|-------------------|
| Shared test state | May require architectural changes |
| Database fixtures | Needs isolation strategy |
| External service calls | Mock design decision |
| Complex async flows | Multiple fix approaches |
```markdown
**Root Cause**: Timing - uses `Date.now()` in assertion
**Confidence**: HIGH (pattern match)
**Auto-fixable**: YES
```typescript
it('should create token with expiry', () => {
const token = createToken();
expect(token.expiresAt).toBeGreaterThan(Date.now());
});
```
```typescript
it('should create token with expiry', () => {
const now = new Date('2024-01-01T12:00:00Z');
vi.setSystemTime(now);
const token = createToken();
expect(token.expiresAt).toBe(now.getTime() + TOKEN_LIFETIME);
vi.useRealTimers();
});
```
- Added: `vi.setSystemTime()` for deterministic time
- Added: `vi.useRealTimers()` cleanup
- Changed: Assertion to exact value match
Run 10x to confirm fix:
```bash
for i in {1..10}; do npm test -- test/api/login.test.ts:45; done
```
| Test | Category | Auto-Fixed | Status |
|------|----------|-----------|--------|
| login.test.ts:45 | Timing | Yes | ✅ Fixed |
| user.test.ts:23 | Async | Yes | ✅ Fixed |
| db.test.ts:67 | State | No | Suggested |
| api.test.ts:12 | Network | No | Suggested |
**Auto-fixed**: 2 tests
**Manual review**: 2 tests
**Estimated stability improvement**: +1.5%
```
- Works with `flaky-detect` for test identification
- Reports to Test Engineer for complex fixes
- Feeds into CI stability metrics
- Updates `.aiwg/testing/flaky-fixes.md`
Analyze and fix flaky tests:
```bash
python scripts/flaky_fixer.py --test test/api/login.test.ts --auto-fix
```
Fix multiple flaky tests:
```bash
python scripts/batch_fix.py --input flaky-report.json --safe-only
```