Objective-C Support
axeDevToolsUIKit.xcframework
Follow the Setup axeDevToolsUIKit.xcframework. Stop at 'Manual Testing' and follow the steps below instead.
Manual Testing
Note: The below snippets are for iOS 13 and higher. Prior to iOS 13, include the below snippets in the AppDelegate's applicationDidBecomeActive
and applicationWillResignActive
Add the below code to SceneDelegate.m:
#import <axeDevToolsUIKit/axeDevToolsUIKit-Swift.h>
Add an AxeDevTools object to your SceneDelegate.m:
@implementation SceneDelegate
AxeDevTools* axeDevTools;
In sceneDidBecomeActive
configure your cloud OR local connection:
Replace 'USERNAME' and 'PASSWORD' with your credentials. Server should be left as an empty String.
// Configure axe DevTools Cloud credentials
NSError* error;
axeDevTools = [AxeDevTools loginWithUsername:@"USERNAME"
andPassword:@"PASSWORD"
toServer:@""
error:&error];
[axeDevTools showA11yFABWithCustomFAB:[[A11yFAB alloc] init]];
// Configure local connection:
// Important: Adjust Info.plist settings for local networking.
NSError* error;
axeDevTools = [AxeDevTools setLocalConnectionAndReturnError:&error];
[axeDevTools showA11yFABWithCustomFAB:[[A11yFAB alloc] init]];
In sceneWillResignActive
stop testing and remove the floating action button.
[axeDevTools hideA11yFAB];
From here, you can now run your application to access the floating action button. The button can be moved around the screen to not obstruct development. When you're ready for a scan, tap the button and a scan of the current screen will be sent to axe DevTools Mobile Dashboard where you can view the results.
Unit Testing
First you will need to initiate the axe DevTools object. We recommend utilizing the setUp
method within your test file. If you prefer, you can also use username and password here instead (code snippet available in Manual Testing).
AxeDevTools* axeDevTools;
- (void)setUp {
NSError* error;
axeDevTools = [AxeDevTools loginWithAPIKey:@"API_KEY"
toServer:@""
error:&error];
}
Then, you can begin testing your app for accessibility issues!
Testing Views on Storyboards
To test the initial view of a storyboard:
NSError* error;
AxeResult* result = [axeDevTools runOnStoryboardName:@"Main"
viewControllerId:@""
bundle:nil
error:&error];
XCTAssertEqual(result.failures.count, 0); // This allows you to assert if there are accessibility failures
Note that you can change which view controller within the storyboard is tested by passing in the view controller's id. If an empty string is passed, the framework will scan the initial view controller of the storyboard.
Testing View Controllers
If your view controllers are created programmatically, pass in an instance of your view controller to the run
method:
NSError* error;
AxeResult* result = [axeDevTools runOnViewController:UIViewController()
error:&error];
XCTAssertEqual(result.failures.count, 0); // This allows you to assert if there are accessibility failures
Testing Views
If you would prefer to only test individual views for accessibility issues, pass in an instance of your view to the run
method:
NSError* error;
AxeResult* result = [axeDevTools runOnView: UIView() error: &error];
XCTAssertEqual(result.failures.count, 0); // This allows you to assert if there are accessibility failures
Send Scans to Dashboard
Utilize postResult
if you would like to send the scan to the Dashboard:
[axeDevTools postResult:result withTags:@[@"Build 10.6.1"] withScanName:@"" error:&error];
If you do not want to tag your scan, you can pass in an empty array to the withTags
parameter. If you would like to give the scan a custom scan name, you can pass it into the withScanName
parameter.
UI Testing
First you will need to initiate the axe DevTools object. We recommend utilizing the setUp
method within your test file. If you prefer, you can also use username and password here instead (code snippet available in Manual Testing).
AxeDevTools* axeDevTools;
- (void)setUp {
NSError* error;
axeDevTools = [AxeDevTools loginWithAPIKey:@"API_KEY"
toServer:@""
error:&error];
}
Because the Floating Action Button is still required for UI Testing, first follow the steps in Interactive Testing; but instead of using the A11yFAB
, use the AutomatedTestFAB
. The automated Floating Action Button is invisible so that it will not interfere with any screenshot testing you have but is still programmatically tappable to capture a scan.
Update the showA11yFAB
call to the following:
[axeDevTools showA11yFABWithCustomFAB:[[AutomatedTestFAB alloc] init]];
When you're ready to capture a scan, use the floating action button's accessibility identifier "com.deque.axeDevTools.accessibilityFab" to programmatically tap it and send a scan to the dashboard:
XCUIElement* fab = app.buttons[@"com.deque.axeDevTools.accessibilityFab"];
[fab tap];
Wait for the FAB to return to know it has finished uploading. The FAB's label will now hold a key you can use to retrieve the scan from the server.
XCTAssert([fab waitForExistenceWithTimeout:5]);
AxeDevToolsResultKey* key = [[AxeDevToolsResultKey alloc] initWithFabTitle:fab.label];
With this key, you can now get additional information from the scan such as passes and failures.
NSError* error;
AxeResult* result = [axeDevTools getResult:key error:&error];
XCTAssertEqual(result.failures.count, 0);
You can also update the scan's name or add tags.
NSError* error;
[axeDevTools updateScanName:key to:@"New Scan Name" error:&error];
[axeDevTools tagResult:key withTags:@[@"Sample Tag"] error:&error];
Full Example
#import <axeDevToolsUIKit/axeDevToolsUIKit-Swift.h>
#import <XCTest/XCTest.h>
@interface ObjcUITests : XCTestCase
@end
@implementation ObjcUITests
AxeDevTools* axeDevTools;
- (void)setUp {
self.continueAfterFailure = NO;
NSError* error;
axeDevTools = [AxeDevTools loginWithAPIKey:@"API_KEY"
toServer:@""
error:&error];
}
- (void)testMainScreen {
XCUIApplication *app = [[XCUIApplication alloc] init];
[app launch];
NSError* error;
XCUIElement* fab = app.buttons[@"com.deque.axeDevTools.accessibilityFab"];
[fab tap];
XCTAssert([fab waitForExistenceWithTimeout:5]);
AxeDevToolsResultKey* key = [[AxeDevToolsResultKey alloc] initWithFabTitle:fab.label];
// Update scan name in Dashboard
[axeDevTools updateScanName:key to:@"New Scan Name" error:&error];
// Update tags in Dashboard for scan
[axeDevTools tagResult:key withTags:@[@"Sample Tag"] error:&error];
// Fetch result
AxeResult* result = [axeDevTools getResult:key error:&error];
XCTAssertEqual(result.failures.count, 0);
}
@end
axeDevToolsXCUI.xcframework
Follow the Setup axeDevToolsXCUI.xcframework. All the features available on this page are fully supported in Objective-C. Import the header in any file you plan to use the XCUI framework in:
#import <axeDevToolsXCUI/axeDevToolsXCUI-Swift.h>
Utilize the setUp
method in your UITests to initialize an AxeDevTools object to interact with available features. Generate an API key at axe.deque.com. If preferred, you can instead authenticate with username and password.
@interface ObjcUITests : XCTestCase
@end
@implementation ObjcUITests
AxeDevTools* axeDevTools;
- (void)setUp {
NSError* error;
axeDevTools = [AxeDevTools loginWithAPIKey:@"API_KEY"
toServer:@""
error:&error];
}
Run a Scan
To run a scan on a screen in your application or on any XCUIElement in your application, create a new test case within your UITests and call the run
method within your AxeDevTools
object:
- (void)testAccessibilityOfFirstScreen {
XCUIApplication *app = [[XCUIApplication alloc] init];
[app launch];
NSError* error;
AxeResult* result = [axeDevTools runOnElement:app error:&error];
XCTAssertEqual(result.failures.count, 0); // This allows you to assert if there are accessibility failures
}
Send Scan to the Dashboard
Once you have the scan, you can send it to the Dashboard by calling the postResult
method from the AxeDevTools
object:
NSError* error;
[axeDevTools postResult:result withTags:@[@"Build 10.6.1"] withScanName:@"" error:&error];
If you do not want to tag your scan, you can pass in an empty array to the withTags
parameter. If you would like to give the scan a custom scan name, you can pass it into the withScanName
parameter.
Full Example
#import <axeDevToolsXCUI/axeDevToolsXCUI-Swift.h>
#import <XCTest/XCTest.h>
@interface ObjcUITests : XCTestCase
@end
@implementation ObjcUITests
AxeDevTools* axeDevTools;
- (void)setUp {
NSError* error;
axeDevTools = [AxeDevTools loginWithAPIKey:@"API_KEY"
toServer:@""
error:&error];
}
- (void)testAccessibilityOfFirstScreen {
XCUIApplication *app = [[XCUIApplication alloc] init];
[app launch];
NSError* error;
AxeResult* result = [axeDevTools runOnElement:app error:&error];
XCTAssertEqual(result.failures.count, 0);
[axeDevTools postResult:result
withTags:@[@"Build 10.6.1"]
withScanName:@""
error:&error];
}
@end
Features in Both Frameworks
Ignoring Views
Once you're logged in, use the AxeDevTools object to ignore rules for specific views. You can ignore all views of a specific class, or ignore a view with a specific Accessibility Identifier:
NSDictionary* ignoreRules = @{ @"UILabel": @[@"InScrollView"], // ignore InScrollView for all UILabels
@"LoginScreen.Button": @[@"TouchTargetSize"] // ignore TouchTargetSize for the view with this accessibility id
};
[[axeDevTools configuration] ignoreWithRulesFor: ignoreRules];
Ignoring Rules
Once you're logged in, use the AxeDevTools object to ignore any rules for an entire scan:
[[axeDevTools configuration] ignoreWithRules:@[@"A11yElementFocusBox"] :true];
You can also re-add rules to the configuration by changing the bool
from true
to false
:
[[axeDevTools configuration] ignoreWithRules:@[@"A11yElementFocusBox"] :false];
Save Scans Locally
Save results locally to utilize the Desktop app, or utilize the axe DevTools reporting tool to build an executive report off a set of scans within your CI/CD pipeline.
A scan will be saved as a .json file. Saving scans locally is only supported within automated testing. If the path and file name are not specified, the results will be named "(APPID)-(CURRENT_SCREEN_TITLE).json" and will be saved in a folder called "AxeDevToolsResults" within your User folder.
Once logged in, use the AxeDevTools object to save your scan as a JSON file. To use the default path and file name, send empty strings to the parameters:
NSError* error;
[axeDevTools saveResult:result toPath:@"" withName:@"" error:&error];