AccessibilitySnapshot

repository·main·Indexed 20 days ago

https://github.com/cashapp/accessibilitysnapshot

A framework for adding accessibility regression tests to iOS apps by providing snapshots of the accessibility hierarchy. It features a core parser (AccessibilitySnapshotCore) and integration layers for SnapshotTesting and iOSSnapshotTestCase. The library allows developers to assert the accessibility hierarchy of a view as an image, with support for mocking inverted colors and Dynamic Type settings.

Tokens
2.9K
Snippets
9
Records
20
Agent score
70%

What's inside AccessibilitySnapshot

  1. Understand Beta Versioning rules

    main

    Because AccessibilitySnapshot is currently in beta, the standard Semantic Versioning rules are modified. Until the 1.0 release:

    • MAJOR version is always 0.
    • Breaking changes (which would normally increment the MAJOR version) increment the MINOR version.
    • All other changes (which would normally increment MINOR or PATCH) increment the PATCH version.
  2. Understand the AccessibilitySnapshot architecture

    main

    AccessibilitySnapshot is structured into two distinct layers to separate parsing logic from snapshotting engines:

    1. AccessibilitySnapshotCore: The foundational layer containing the core accessibility parser and utilities. It includes tools for generating a container view for snapshots that features a legend describing each accessibility element within the view.
    2. Integration Layers: Built on top of the core parser to provide seamless testing with existing snapshotting frameworks.

    Developers can choose to use the pre-built integration layers or build their own custom integration by depending directly on AccessibilitySnapshotCore.

  3. Determine compatibility when updating AccessibilitySnapshot

    main

    When deciding whether to update the library in your project, use the following compatibility guarantees based on the version change:

    • PATCH version change only (0.x.y -> 0.x.y+1): Guaranteed to compile and pass existing tests.
    • MINOR or PATCH version change (0.x.y -> 0.x+1.y): Guaranteed to compile. Tests are guaranteed to pass only if the contents of the tests were correct originally.
    • MAJOR version change: Not guaranteed to compile or pass tests.
  4. Ensure accessibility properties are populated with ASAccessibilityEnabler

    main
    The ASAccessibilityEnabler class is responsible for enabling accessibility on the simulator. It is automatically triggered via the +load method, so manual activation is typically not required in your integration layer. If this class does not run, UIKit may fail to automatically populate many accessibility properties, leading to incomplete or missing data in your snapshots.
  5. How to output accessibility hierarchy snapshot images

    main

    To output snapshot images of an accessibility hierarchy in a view-based integration, use the AnimationSnapshotView. This class acts as a container view that wraps the view being snapshotted, along with the necessary highlights and legend views required for the snapshot output.

    /* Use AnimationSnapshotView as the primary container for view-based snapshotting integrations. */
  6. Use AccessibilitySnapshot with SnapshotTesting

    main

    If your project uses SnapshotTesting, you can use the .accessibilityImage snapshotting strategy. This allows you to assert the accessibility hierarchy of a view as an image.

    You can customize the visibility of accessibility activation point indicators using the showActivationPoints parameter. The available options are .always, .never, or the default behavior (only showing indicators when the activation point differs from the view's default).

    func testAccessibility() {
        let view = MyView()
        // Configure the view...
    
        // Default behavior
        assertSnapshot(matching: view, as: .accessibilityImage)
    
        // Show indicators for every element
        assertSnapshot(matching: view, as: .accessibilityImage(showActivationPoints: .always))
    
        // Don't show any indicators
        assertSnapshot(matching: view, as: .accessibilityImage(showActivationPoints: .never))
    }
  7. Run the demo app on physical hardware

    main

    To run the example project on a real device instead of a simulator, you must provide an Apple development team ID during the Tuist generation process. You can either set the TUIST_DEVELOPMENT_TEAM environment variable in your shell configuration or pass it inline to the command.

    # Option 1: Inline command
    TUIST_DEVELOPMENT_TEAM=ABCDEFG123 tuist generate --path Example
    
    # Option 2: Add to .zshrc or .bashrc
    export TUIST_DEVELOPMENT_TEAM=ABCDEFG123
  8. Use AccessibilitySnapshot with iOSSnapshotTestCase

    main

    If your project uses iOSSnapshotTestCase, use the SnapshotVerifyAccessibility method to perform tests. This method supports standard iOSSnapshotTestCase features like recordMode and custom identifiers.

    Similar to the SnapshotTesting integration, you can control the visibility of activation point indicators using the showActivationPoints parameter with .always or .never.

    // Swift usage
    func testAccessibility() {
        let view = MyView()
        // Configure the view...
    
        // Basic usage
        SnapshotVerifyAccessibility(view)
    
        // With a custom identifier
        SnapshotVerifyAccessibility(view, identifier: "identifier")
    
        // Controlling activation point indicators
        SnapshotVerifyAccessibility(view, showActivationPoints: .always)
        SnapshotVerifyAccessibility(view, showActivationPoints: .never)
    }
    
    // Objective-C usage
    - (void)testAccessibility;
    {
        UIView *view = [UIView new];
        // Configure the view...
    
        SnapshotVerifyAccessibility(view, @"identifier");
    }
  9. Install AccessibilitySnapshot via Swift Package Manager

    main

    To use AccessibilitySnapshot, add it as a dependency in your Package.swift.

    By default, the package uses SnapshotTesting as the engine. If you only need the core accessibility parser without the snapshotting logic, you can depend on AccessibilitySnapshotCore instead.

    If you intend to use iOSSnapshotTestCase as your snapshotting engine, you must add the specific compatibility dependency: FBSnapshotTestCase+Accessibility for Swift or FBSnapshotTestCase+Accessibility-ObjC for Objective-C.

    // Add to dependencies
    dependencies: [
        .package(name: "AccessibilitySnapshot", url: "https://github.com/cashapp/AccessibilitySnapshot.git", from: "0.4.1"),
    ]
    
    // Add to test target
    targets: [
        .target(name: "MyApp"),
        .testTarget(name: "MyAppTests", dependencies: ["MyApp", "AccessibilitySnapshot"])
    ]