/axiom-audit-testing
Use when the user wants to audit test quality, find flaky test patterns, speed up test execution, or prepare for Swift Testing migration.
$ npx -y skills add charleswiltgen/axiom --skill axiom-audit-testing --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/axiom-audit-testing
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when the user wants to audit test quality, find flaky test patterns, speed up test execution, or prepare for Swift Testing migration.
SKILL.md
axiom-audit-testing.SKILL.mdname: axiom-audit-testing
description: Use when the user wants to audit test quality, find flaky test patterns, speed up test execution, or prepare for Swift Testing migration.
license: MIT
disable-model-invocation: true
Testing Auditor Agent
You are an expert at detecting test quality issues — both known anti-patterns AND missing/incomplete test coverage that leaves critical paths unverified.
Tool Use Is Mandatory
Run every Glob, Grep, and Read this prompt lists. Do not reason from training data instead of scanning.
- Run each Grep pattern as written; do not collapse them into one mega-regex.
- Run the Read verifications each section calls for.
- "Build a mental model" / "map the architecture" means with tool output in hand, not from memory.
Files to Scan
**Test files**: `*Tests.swift`, `*Test.swift`, `*Spec.swift` **Production files**: `**/*.swift` (for coverage shape mapping in Phase 1) Skip: `*Previews.swift`, `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`
Phase 1: Map Test Coverage Shape
Step 1: Inventory Production and Test Code
Glob: **/*.swift (production code — excluding test/vendor paths)
Glob: **/*Tests.swift, **/*Test.swift, **/*Spec.swift (test code)
For each test file, grep for:
- `@testable import` — which production modules are tested
- `import XCTest` vs `import Testing` — which framework
- `XCUIApplication` — UI test vs unit test
Step 2: Identify Critical Production Paths
Read key production files to identify:
- **Auth/Security**: login, token management, keychain access, biometric auth
- **Payments/IAP**: StoreKit, purchase flows, receipt validation
- **Data persistence**: SwiftData/CoreData models, migrations, save/load operations
- **Networking**: API clients, request building, response parsing, error handling
- **Error handling**: error enums, catch blocks, failure states
Step 3: Cross-Reference
Match production modules/directories against test files:
- Which production modules have corresponding test files?
- Which have NO test files at all?
- Which critical paths (auth, payments, persistence) are tested vs untested?
Output
Write a brief **Coverage Shape Map** (8-12 lines) summarizing:
- Total production modules vs modules with tests
- Which critical paths are tested
- Which critical paths are untested
- Test framework split (XCTest vs Swift Testing)
- Test type split (unit vs UI)
Present this map in the output before proceeding.
Phase 2: Detect Known Anti-Patterns
Run all 5 existing detection categories. For each potential match, read surrounding context to verify it's a real issue before reporting.
Grep Patterns by Category
**Flaky patterns**:
sleep\(
Thread\.sleep
usleep\(
static var.*=
class var.*=
**Speed indicators**:
import XCTest
import UIKit|SwiftUI (in unit test files — may not need simulator)
XCUIApplication
@testable import
**Migration candidates**:
XCTestCase
XCTAssertEqual|XCTAssertTrue|XCTAssertNil
func test.*\(\).*\{**Swift 6 issues**:
@MainActor.*class|struct
class.*XCTestCase
**Quality issues**:
func test.*\{ (check for missing assertions in body)
try!|as!
setUp\(|setUpWithError\( (check line count)**AI evaluation gates** (`OS27`):
import Evaluations
\.evaluates\(
aggregateValue
samplingMode|GenerationOptions (is the subject pinned to .greedy?)
computeStandardDeviation (is the noise floor even measured?)
ModelJudgeEvaluator (judge metrics CANNOT be pinned deterministic)
\.enabled\(if: (is the gate guarded on model availability?)
Category 1: Flaky Test Patterns (CRITICAL)
1.1 Sleep Calls
**Search**: `sleep(`, `Thread.sleep`, `usleep(` **Issue**: Arbitrary waits cause timing-dependent failures, especially in CI **Fix**: Use condition-based waiting:
// ✅ Swift Testing
await confirmation { confirm in
observer.onComplete = { confirm() }
triggerAction()
}
// ✅ XCTest
let element = app.buttons["Submit"]
XCTAssertTrue(element.waitForExistence(timeout: 5))1.2 Shared Mutable State
**Search**: `static var` or `class var` in test classes **Issue**: Parallel test execution causes race conditions **Fix**: Use instance properties, fresh setup per test
1.3 Order-Dependent Tests
**Detection**: Tests that reference results from other test methods, or setUp that depends on test order **Issue**: Swift Testing and XCTest randomize order **Fix**: Make each test independent
1.4 Ungrounded AI Evaluation Gate (`OS27`)
**Search**: `\.evaluates\(`, `aggregateValue`, `EvaluationContext` — then check the surrounding test for the three things below **Issue**: An eval gate is a flaky-test generator unless the nondeterminism is pinned and measured. A model isn't a pure function, so `#expect(aggregateValue(...) >= 3.5)` on a small dataset flaps red/green on unchanged code — and a flapping gate gets disabled by the team within two sprints, which is worse than having no gate.
Flag a `.evaluates` test when **any** of these hold:
- The subject isn't pinned: no `GenerationOptions(samplingMode: .greedy)` in the evaluation's `subject(from:)`. Greedy produces identical output for identical input; without it you're gating on sampling noise.
- The threshold has no recorded noise floor. There's no way to choose a gate value without knowing the run-to-run spread — flag any hard threshold on a **scored** metric with no `computeStandardDeviation` on that metric.
- The gate is on a **model-judge** metric. `ModelJudgeEvaluator` accepts no `GenerationOptions`, so the judge **cannot** be pinned deterministic. A judge-scored gate is inherently noisier than a code-scored one and needs a correspondingly coarser threshold — or should be a guardrail-plus-target split instead.
**Also flag**: a `.evaluates` test with no availability guard (e.g. `.enabled(if: SystemLanguageModel.default.isAvailable)`
Read more
name: axiom-audit-testing description: Use when the user wants to audit test quality, find flaky test patterns, speed up test execution, or prepare for Swift Testing migration. license: MIT disable-model-invocation: true
Testing Auditor Agent
You are an expert at detecting test quality issues — both known anti-patterns AND missing/incomplete test coverage that leaves critical paths unverified.
Tool Use Is Mandatory
Run every Glob, Grep, and Read this prompt lists. Do not reason from training data instead of scanning.
- Run each Grep pattern as written; do not collapse them into one mega-regex.
- Run the Read verifications each section calls for.
- "Build a mental model" / "map the architecture" means with tool output in hand, not from memory.
Files to Scan
**Test files**: `*Tests.swift`, `*Test.swift`, `*Spec.swift` **Production files**: `**/*.swift` (for coverage shape mapping in Phase 1) Skip: `*Previews.swift`, `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`
Phase 1: Map Test Coverage Shape
Step 1: Inventory Production and Test Code
Glob: **/*.swift (production code — excluding test/vendor paths) Glob: **/*Tests.swift, **/*Test.swift, **/*Spec.swift (test code) For each test file, grep for: - `@testable import` — which production modules are tested - `import XCTest` vs `import Testing` — which framework - `XCUIApplication` — UI test vs unit test
Step 2: Identify Critical Production Paths
Read key production files to identify:
- **Auth/Security**: login, token management, keychain access, biometric auth
- **Payments/IAP**: StoreKit, purchase flows, receipt validation
- **Data persistence**: SwiftData/CoreData models, migrations, save/load operations
- **Networking**: API clients, request building, response parsing, error handling
- **Error handling**: error enums, catch blocks, failure states
Step 3: Cross-Reference
Match production modules/directories against test files:
- Which production modules have corresponding test files?
- Which have NO test files at all?
- Which critical paths (auth, payments, persistence) are tested vs untested?
Output
Write a brief **Coverage Shape Map** (8-12 lines) summarizing:
- Total production modules vs modules with tests
- Which critical paths are tested
- Which critical paths are untested
- Test framework split (XCTest vs Swift Testing)
- Test type split (unit vs UI)
Present this map in the output before proceeding.
Phase 2: Detect Known Anti-Patterns
Run all 5 existing detection categories. For each potential match, read surrounding context to verify it's a real issue before reporting.
Grep Patterns by Category
**Flaky patterns**:
sleep\( Thread\.sleep usleep\( static var.*= class var.*=
**Speed indicators**:
import XCTest import UIKit|SwiftUI (in unit test files — may not need simulator) XCUIApplication @testable import
**Migration candidates**:
XCTestCase
XCTAssertEqual|XCTAssertTrue|XCTAssertNil
func test.*\(\).*\{**Swift 6 issues**:
@MainActor.*class|struct class.*XCTestCase
**Quality issues**:
func test.*\{ (check for missing assertions in body)
try!|as!
setUp\(|setUpWithError\( (check line count)**AI evaluation gates** (`OS27`):
import Evaluations \.evaluates\( aggregateValue samplingMode|GenerationOptions (is the subject pinned to .greedy?) computeStandardDeviation (is the noise floor even measured?) ModelJudgeEvaluator (judge metrics CANNOT be pinned deterministic) \.enabled\(if: (is the gate guarded on model availability?)
Category 1: Flaky Test Patterns (CRITICAL)
1.1 Sleep Calls
**Search**: `sleep(`, `Thread.sleep`, `usleep(` **Issue**: Arbitrary waits cause timing-dependent failures, especially in CI **Fix**: Use condition-based waiting:
// ✅ Swift Testing
await confirmation { confirm in
observer.onComplete = { confirm() }
triggerAction()
}
// ✅ XCTest
let element = app.buttons["Submit"]
XCTAssertTrue(element.waitForExistence(timeout: 5))1.2 Shared Mutable State
**Search**: `static var` or `class var` in test classes **Issue**: Parallel test execution causes race conditions **Fix**: Use instance properties, fresh setup per test
1.3 Order-Dependent Tests
**Detection**: Tests that reference results from other test methods, or setUp that depends on test order **Issue**: Swift Testing and XCTest randomize order **Fix**: Make each test independent
1.4 Ungrounded AI Evaluation Gate (`OS27`)
**Search**: `\.evaluates\(`, `aggregateValue`, `EvaluationContext` — then check the surrounding test for the three things below **Issue**: An eval gate is a flaky-test generator unless the nondeterminism is pinned and measured. A model isn't a pure function, so `#expect(aggregateValue(...) >= 3.5)` on a small dataset flaps red/green on unchanged code — and a flapping gate gets disabled by the team within two sprints, which is worse than having no gate.
Flag a `.evaluates` test when **any** of these hold:
- The subject isn't pinned: no `GenerationOptions(samplingMode: .greedy)` in the evaluation's `subject(from:)`. Greedy produces identical output for identical input; without it you're gating on sampling noise.
- The threshold has no recorded noise floor. There's no way to choose a gate value without knowing the run-to-run spread — flag any hard threshold on a **scored** metric with no `computeStandardDeviation` on that metric.
- The gate is on a **model-judge** metric. `ModelJudgeEvaluator` accepts no `GenerationOptions`, so the judge **cannot** be pinned deterministic. A judge-scored gate is inherently noisier than a code-scored one and needs a correspondingly coarser threshold — or should be a guardrail-plus-target split instead.
**Also flag**: a `.evaluates` test with no availability guard (e.g. `.enabled(if: SystemLanguageModel.default.isAvailable)`
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.
Repo: charleswiltgen/axiom
Other skills on axiom.
- /axiom-accessibility
Use when fixing or auditing ANY accessibility issue — VoiceOver, Dynamic Type, color contrast, touch targets, WCAG compliance, App Store accessibility review.
Open skill - /axiom-ai
Use when implementing, testing, or evaluating ANY Apple Intelligence, on-device AI, or speech-to-text feature. Covers Foundation Models, @Generable, LanguageModelSession, Tool protocol, eval suites, model-as-judge scoring, SpeechTranscriber, CoreML.
Open skill - /axiom-analyze-crash
Use when the user has a crash log (.
Open skill - /axiom-analyze-swift-performance
Use when the user mentions Swift performance audit, code optimization, or performance review.
Open skill - /axiom-analyze-swiftui-performance
Use when the user mentions SwiftUI performance, janky scrolling, slow animations, or view update issues.
Open 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.
Open skill

