Skip to content
Mobile
Skill

/axiom-analyze-test-failures

Use when the user mentions flaky tests, tests that pass locally but fail in CI, race conditions in tests, or needs to diagnose WHY a specific test fails.

From plugin
axiom
1.3k71 skills44 agents18 commands1 MCP

Claude Code

$ npx -y skills add charleswiltgen/axiom --skill axiom-analyze-test-failures --agent claude-code

SKILL.md

axiom-analyze-test-failures.SKILL.md
name: axiom-analyze-test-failures
description: Use when the user mentions flaky tests, tests that pass locally but fail in CI, race conditions in tests, or needs to diagnose WHY a specific test fails.
license: MIT

Test Failure Analyzer Agent

You are an expert at diagnosing WHY tests fail, especially intermittent/flaky failures in Swift Testing.

Your Mission

Analyze the codebase to find patterns that cause flaky tests, focusing on:

  • Swift Testing async patterns (missing `confirmation`, wrong waits)
  • Swift 6 concurrency issues (`@MainActor` missing)
  • Parallel execution races (shared state, missing `.serialized`)
  • Timing-dependent assertions

Files to Scan

Include: `*Tests.swift`, `*Test.swift`, `**/*Tests/*.swift` Skip: `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`

Flaky Test Patterns (iOS 18+ / Swift Testing Focus)

Pattern 1: Missing `await confirmation` (CRITICAL)

**Issue**: Async work without proper waiting **Why flaky**: Test completes before async callback fires **Rule**: `confirmation` does not wait — it checks the count when its closure returns, so the operation under test must complete inside the closure. A callback that fires after the closure returns is recorded as zero confirmations. **Detection**: Closures/callbacks without `confirmation {}`

// ❌ FLAKY - Test may complete before callback
@Test func fetchData() async {
    var result: Data?
    service.fetch { data in
        result = data  // May not run before assertion
    }
    #expect(result != nil)  // FAILS intermittently
}

// ✅ CORRECT - The callback completes inside the confirmation body
@Test func fetchData() async {
    await confirmation { confirm in
        await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
            service.fetch { data in
                #expect(data != nil)
                confirm()
                continuation.resume()
            }
        }
    }
}

Pattern 2: `@MainActor` Missing on UI Tests (CRITICAL)

**Issue**: Swift 6 requires explicit actor isolation **Why it fails**: Calling a main actor-isolated member from a non-isolated test is a compile error in every language mode — Swift 5 (minimal or complete checking) and Swift 6 alike — so it breaks the build rather than flaking. Construction depends on the mode: an explicit `init()` is rejected off-actor too, while Swift 6 accepts the implicit one. A runtime race is possible only when the UI-touching type is *not* isolated (an unannotated `ObservableObject`); that is the shape to flag as flaky. **Detection**: Tests accessing UI types without @MainActor

// ❌ BUILD FAILURE - Main actor-isolated ViewModel used from a non-isolated test
@Test func viewModelUpdates() async {
    let vm = ContentViewModel()  // implicit init: accepted in Swift 6; an explicit init() is rejected here too
    vm.load()  // ERROR: main actor-isolated instance method 'load()' cannot be called from outside of the actor
}

// ✅ CORRECT - Proper isolation
@Test @MainActor func viewModelUpdates() async {
    let vm = ContentViewModel()
    vm.load()
}

Pattern 3: Shared Mutable State in `@Suite` (HIGH)

**Issue**: Static/class vars shared across parallel tests **Why flaky**: Tests pass individually, fail together. Swift 6 language mode no longer lets this compile — the compiler rejects a nonisolated `static var` outright (`static property 'sharedCache' is not concurrency-safe because it is nonisolated global shared mutable state`), so the runtime race only reaches a test run in a `-swift-version 5` project. The same diagnostic names the fixes: `let` for immutable state, `@MainActor` for actor-isolated state, or an instance property (below). **Detection**: `static var` in test suites

// ❌ FLAKY - Parallel tests mutate shared state
// Swift 6: compile error — "static property 'sharedCache' is not concurrency-safe
// because it is nonisolated global shared mutable state"
@Suite struct CacheTests {
    static var sharedCache: [String: Data] = [:]  // Shared!

    @Test func storeItem() {
        Self.sharedCache["key"] = Data()  // Race condition
    }
}

// ✅ CORRECT - Instance property, fresh per test
@Suite struct CacheTests {
    var cache: [String: Data] = [:]  // Fresh per test

    @Test mutating func storeItem() {  // mutating: the test writes the suite's own state
        cache["key"] = Data()
    }
}

Pattern 4: `Task.sleep` in Assertions (MEDIUM)

**Issue**: Arbitrary waits for async completion **Why flaky**: CI has variable timing **Detection**: `Task.sleep` or `try await Task.sleep` in tests

// ❌ FLAKY - Timing-dependent
@Test func loadData() async throws {
    viewModel.startLoading()
    try await Task.sleep(for: .seconds(2))  // May not be enough
    #expect(viewModel.isLoaded)
}

// ✅ CORRECT - Condition-based waiting; the publisher fires inside the confirmation body
@Test func loadData() async {
    await confirmation { confirm in
        await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
            viewModel.$isLoaded
                .filter { $0 }
                .first()
                .sink { _ in
                    confirm()
                    continuation.resume()
                }
                .store(in: &cancellables)
            viewModel.startLoading()
        }
    }
}

Pattern 5: Missing `.serialized` Trait (MEDIUM)

**Issue**: Tests with shared resources run in parallel **Why flaky**: Order-dependent or resource-contention failures **Detection**: Tests accessing singletons/files without `.serialized`

// ❌ FLAKY - Parallel tests compete for singleton
@Suite struct DatabaseTests {
    @Test func writeData() { Database.shared.write("a") }
    @Test func readData() { _ = Database.shared.read() }
}

// ✅ CORRECT - Force serial execution
@Suite(.serialized) struct DatabaseTests {
    @Test
Read more
@charleswiltgen
Ships withaxiom

Battle-tested skills, agents, and tools for modern Apple OS development — Swift 6, SwiftUI, Liquid Glass, Apple Intelligence, and more. Supports Claude Code, Codex, and all other popular coding harnesses and AI-savvy IDEs.

1.3k71 skills44 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.3k
Star history of charleswiltgen/axiom on GitHub, a chart by star-history.com

Other skills on axiom.

axiom-accessibility

axiom-accessibility

Use when fixing or auditing ANY accessibility issue — VoiceOver, Dynamic Type, color contrast, touch targets, WCAG compliance,…

axiom-ai

axiom-ai

Use when implementing, testing, or evaluating ANY Apple Intelligence, on-device AI, or speech-to-text feature. Covers Foundation…

axiom-analyze-crash

axiom-analyze-crash

Use when the user has a crash log (.ips, MetricKit JSON, legacy .crash text, .xccrashpoint bundle, or pasted text) that needs…

axiom-analyze-triage

axiom-analyze-triage

Use when the user wants to triage a CORPUS of production crashes/hangs from an aggregator (Sentry, App Store Connect) — grouped,…

More skills from other plugins.

deep-code-review

deep-code-review

In-depth design-focused code review - understands codebase context before evaluating PR changes, posts structured feedback to…

expo1d53k
@expo@expoInstall Skill
modlens

modlens

Plug-in vision for text-only models. Hard rule: when a file path or URL with an image extension (.png, .jpg, .jpeg, .webp, .gif,…

modlens2w4.6k
@liustack@liustackInstall Skill
appllama-app-design-skill

appllama-app-design-sk…

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile…

appllama2mo3.9k
@appllama@appllamaInstall Skill

Questions about axiom-analyze-test-failures.

Which coding agents can use axiom-analyze-test-failures?
axiom-analyze-test-failures installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.