Auto Scan
Automatically identify accessibility issues as your existing XCUITests interact with your app
Overview
Hooking into standard XCUITest gestures, Auto Scan captures and scans every screen your test suite interacts with, without the need to add individual scan calls, imports, or modifications to your tests.
How it works
- When the test bundle starts, Auto Scan loads
axe_config.jsonand begins observing interactions - After each supported interaction, Auto Scan captures the current screen
- When the test bundle finishes, Auto Scan processes your results, saves a JSON result for each screen - along with a summary and an HTML report - to
AxeDevToolsMobileResults/, and optionally uploads results to Developer Hub
Getting Started
- Create
axe_config.json:
{
"axeAutoScanMode": true,
"axeAppBundleId": "com.example.myapp",
"axeMobileApiKey": "<API_KEY>",
"axeProjectId": "<PROJECT_ID>"
}- Add
axe_config.jsonto UI test target bundle in Xcode (Project Navigator > Add Files > Check the UI test target) - Add
axe_config.jsonto.gitignore - Run tests normally
Example Code
The snippet below is a standard XCUITest, with no Auto Scan-specific code:
import XCTest
class MyAppUITests: XCTestCase {
let app = XCUIApplication()
override func setUpWithError() throws {
app.launch() // triggers initial capture
}
func testSettings() throws {
app.buttons["Settings"].tap() // triggers capture
}
}Interpreting Results
Console summary
A console summary similar to the following is printed when the test suite finishes:
---- Axe DevTools Mobile Accessibility Summary ----
Scan 1:
Screen: HomeScreen
Issues: 3
Issues by rule:
- ColorContrast: 2
- TouchTargetSize: 1
Scan 2:
Screen: SettingsScreen
Issues: 0
Total Scans: 2
❌ Total Issues: 3
----------------------------------------------------A clean run will show Axe Clean - 0 Issues Found 🎉 in the console.
Output files
Auto Scan generates a few different files at the end of each test run, including a self-contained HTML report that includes screenshots, view hierarchy data, and detailed issue information. All files are saved to the AxeDevToolsResults directory.
| File | Format |
|---|---|
AxeDevToolsSummary_<epoch>.txt |
Text summary (same as console output) |
AxeDevToolsReport_<epoch>.html |
Interactive HTML report with per-screen issues, element details, impact levels, view hierarchy |
<bundleId-screenTitle>.json |
Individual JSON result - 1 for each scan taken |
Auto Scan Support
Rules
Auto Scan runs the full Axe rule set with the exception of ScreenOrientation, SupportsDynamicType, and all experimental rules. Find detailed information about what we check for in the Rule Overview for iOS.
Developer Hub
Auto Scan automatically uploads your results to Axe Developer Hub. If you only want to save results locally, set axeUploadResults to false.
Configuration Reference
Properties
| Property | Type | Required | Details |
|---|---|---|---|
axeAutoScanMode |
Boolean | Required | Defaults to false. Must set to true to enable auto scan. |
axeAppBundleId |
String | Required | Bundle ID of the app under test |
axeUploadResults |
Boolean | Optional | Defaults to true. Set to false for local results only |
axeMobileApiKey |
String | Optional | An Axe DevTools Mobile API key from axe.deque.com is required if axeUploadResults=true |
axeProjectId |
String | Optional | A Project ID from Developer Hub is required if axeUploadResults=true |
axeServerUrl |
String | Optional | Custom backend URL, for on-prem/private cloud only |
axeOfflineLicenseKey |
String | Optional | Only required for offline mode, when axeUploadResults=false |
If you are using our tools and prefer to get results in offline mode, you will set a value for the axeOfflineLicenseKey in lieu of axeMobileApiKey and axeProjectId.
Best Practices
Disable Animations
Get the most accurate and comprehensive results from Auto Scan by disabling animation. This will ensure screens are fully rendered when captured.
Both pieces below are required:
Test setup:
override func setUpWithError() throws {
let app = XCUIApplication()
app.launchArguments.append("-DisableAnimations")
app.launch()
}App launch path (AppDelegate or @main):
if ProcessInfo.processInfo.arguments.contains("-DisableAnimations") {
UIView.setAnimationsEnabled(false)
}The launch argument passes the flag to the app process. The app-side check acts on it. Neither works alone.
Note: UIView.setAnimationsEnabled(false) does not cover SwiftUI-native animations (withAnimation {}). SwiftUI apps may need additional handling.
Troubleshooting
- No results? Verify
axe_config.jsonis included in the UI test target bundle. Check Target Membership in XCode's File Inspector. - Seeing results locally, but not in Developer Hub? The upload to Developer Hub fails if the size of any one result file is greater than 20MB, though all the results are still saved locally and shown in the local HTML report.
- Check logs. Look for
AutoScanmessages in the console.
What's Next?
You can view your results in Axe Developer Hub. Learn how to integrate Axe DevTools Mobile in your CI/CD pipeline. Using a cloud-based testing platform? You can still use Axe DevTools Mobile to look for accessibility issues: Integrate with Cloud Platforms.
If you need more granular control in your tests, see Targeted Testing with XCUITest.
