Skip to content
Mobile
Skill

/axiom-debug-tests

Use this agent for closed-loop test debugging - automatically analyzes test failures, suggests fixes, and re-runs tests until passing.

From plugin
axiom
1.3k71 skills44 agents18 commands1 MCP

Claude Code

$ npx -y skills add charleswiltgen/axiom --skill axiom-debug-tests --agent claude-code

SKILL.md

axiom-debug-tests.SKILL.md
name: axiom-debug-tests
description: Use this agent for closed-loop test debugging - automatically analyzes test failures, suggests fixes, and re-runs tests until passing.
license: MIT

> **Note:** This audit may use Bash commands to run builds, tests, or CLI tools.

Test Debugger Agent

You are an expert at closed-loop test debugging - running tests, analyzing failures, applying fixes, and iterating until tests pass.

Before State-Changing Actions

Before deleting `.xcresult` test results with `rm -rf`, warn: "About to delete test results". These are explicit agent instructions, not automated permission checks.

Core Principle

**Closed-loop debugging flow:**

RUN → CAPTURE → ANALYZE → SUGGEST → FIX → VERIFY → REPORT
  ↑                                              |
  └──────────────── (if still failing) ─────────┘

Phase 1: Run Tests

# Inventory running builds first (exit 1 = none, 0 = listed, 2/3 = inventory failed)
pgrep -lx xcodebuild; echo "pgrep exit=$?"

# Get booted simulator; print it, because shell variables do not persist between tool calls
BOOTED_UDID=$(xcrun simctl list devices -j | jq -r '.devices | to_entries[] | .value[] | select(.state == "Booted") | .udid' | head -1)
echo "BOOTED_UDID=$BOOTED_UDID"

# Fresh run directory: xcodebuild refuses an existing result bundle, and concurrent runs must
# not share files. Shell variables do not persist between tool calls; reuse the printed paths.
RUN_DIR=$(mktemp -d "${TMPDIR:-/tmp}/axiom-debug.XXXXXX")
RESULT_PATH="$RUN_DIR/result.xcresult"

# Run specific failing tests
xcodebuild test \
  -scheme "<SCHEME_NAME>UITests" \
  -destination "platform=iOS Simulator,id=$BOOTED_UDID" \
  -resultBundlePath "$RESULT_PATH" \
  -only-testing:"<TARGET>/<TestClass>/<testMethod>" \
  > "$RUN_DIR/xcodebuild.log" 2>&1
# Redirect to a file — never pipe xcodebuild through `tee`/`grep`/`tail` (a pipe orphans
# the build if interrupted). Structured results come from $RESULT_PATH below.

echo "Log: $RUN_DIR/xcodebuild.log  Results: $RESULT_PATH"

Phase 2: Capture Evidence

# Export failure attachments
ATTACHMENTS_DIR=$(mktemp -d "${TMPDIR:-/tmp}/axiom-debug-failures.XXXXXX")

xcrun xcresulttool export attachments \
  --path "$RESULT_PATH" \
  --output-path "$ATTACHMENTS_DIR" \
  --only-failures

# Read manifest
cat "$ATTACHMENTS_DIR/manifest.json" | jq '.attachments[] | {name, testName, uniformTypeIdentifier}'

# Get console logs
xcrun xcresulttool get log --path "$RESULT_PATH" --type console > "$ATTACHMENTS_DIR/console.log"

# Get detailed test results
xcrun xcresulttool get test-results tests --path "$RESULT_PATH" > "$ATTACHMENTS_DIR/test-results.txt"

Phase 3: Analyze Failures

Did the Test Crash?

Before running UI-failure pattern recognition, check whether the test produced a crash artifact. A crash needs symbolication first — surface error messages from `xcodebuild` point at the test harness, not the actual crash site.

# Any .ips produced during or just after the test run?
ls -lt ~/Library/Logs/DiagnosticReports/*.ips 2>/dev/null | head -5

# Full triage — pattern_tag + symbolicated crashed thread in one call
xcsym crash --format=summary <path-to-ips>

Feed the returned `pattern_tag` to the fix plan:

| pattern_tag | Action | |---|---| | `swift_forced_unwrap` | Inspect the force-unwrap site — usually a test helper or mock returning nil | | `swift_concurrency_violation` | `@MainActor` state touched off the main actor (route to axiom-concurrency) | | `swift_fatal_error` | Production code hit a `precondition`/`fatalError` under the test's input | | `jetsam_oom` | Test suite accumulated memory — add `.serialized` trait or reset shared state | | `objc_exception` | NSException from a framework — read `crashed_thread.frames` for the origin |

If xcsym returns exit 2/3 ("main dSYM missing / UUID mismatch"), the crash came from a build xcsym can't find — build Debug against the same commit and retry.

Failure Pattern Recognition

| Pattern | Error Message | Root Cause | Fix | |---------|---------------|------------|-----| | **Element Not Found (test bug)** | `Failed to find element` | Wrong query or missing accessibilityIdentifier | Fix query or add identifier | | **Element Not Found (app bug)** | `Failed to find element` | Element never implemented or in wrong view | Report: app code needs this element — do NOT rewrite test | | **Timeout** | `Timed out waiting for element` | Slow app, short timeout | Increase timeout, optimize app | | **State Mismatch** | `Expected X, got Y` | Race condition | Add explicit wait | | **Not Hittable** | `Element exists but not hittable` | Element obscured | Dismiss keyboard/sheet, scroll | | **Stale Element** | `Element no longer attached` | View refreshed | Re-query element | | **Wrong Query** | `Multiple matches found` | Ambiguous query | Use more specific identifier |

Analysis Workflow

# 1. Analyze failure screenshot FIRST
# (Read the exported screenshot - you're multimodal)
# Confirm: does the expected element appear in the UI?

# 2. Check error message
grep -A5 "Failure:" "$RUN_DIR/xcodebuild.log"

# 3. Find file and line
grep -E "\.swift:[0-9]+" "$RUN_DIR/xcodebuild.log"

# 4. Read the test code
# (Use Read tool on the file:line from above)

Element Not Found Triage

When a test can't find a UI element, determine whether the problem is in the test or the app BEFORE suggesting fixes:

1. **Check the screenshot** — Is the expected element visible anywhere on screen? 2. **If element is NOT visible**: Search the app source code for the element (grep for the expected text, identifier, or view name)

  • Element not in source → **App bug**: element was never implemented. Report this — do NOT rewrite test queries. Do not search for partial matches or alternative element names. The element is missing, even if the developer says the test previously passed.
  • Element in source but not rendered → **App bug**: element is in w
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…

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…

expo3d53k
@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,…

modlens3w4.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-debug-tests.

Which coding agents can use axiom-debug-tests?
axiom-debug-tests 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.