Skip to main content

Accessibility Assertions (axe-core)

Selenium Boot 2.5.0 bundles axe-core 4.10.2 directly in the JAR. Call accessibility() after open() to run a WCAG scan with zero extra dependencies.


Quick example

public class CheckoutAccessibilityTest extends BaseTest {

@Test
public void checkout_passesWCAG21AA() {
open("/checkout");

accessibility()
.withTags("wcag2a", "wcag21aa") // WCAG 2.1 AA rules only
.withLevel(Impact.SERIOUS) // fail on SERIOUS or CRITICAL
.excluding("#cookie-banner") // skip third-party widget
.run();
}
}

API reference

accessibility() — entry point

Available in BaseTest and BaseJUnit5Test. Returns an AccessibilityAssert builder.

Builder methods

MethodDescription
.withTags(String... tags)Run only rules matching the given axe-core tags. Common: "wcag2a", "wcag2aa", "wcag21aa", "wcag22aa", "best-practice". Default: all rules.
.withLevel(Impact minimum)Fail only on violations at or above this severity. Default: Impact.MINOR (all violations fail).
.excluding(String... selectors)CSS selectors to exclude from the scan. Subtrees rooted at these elements are ignored.
.withContext(String selector)Restrict the scan to the subtree rooted at this CSS selector.

Terminal methods

MethodDescription
.run()Execute scan and throw AssertionError if violations are found at the configured level.
.collect()Execute scan and return AccessibilityResult without asserting.

Impact levels

Impact.CRITICAL   // inaccessible to assistive technology users
Impact.SERIOUS // severe barrier with possible workarounds
Impact.MODERATE // degraded experience without complete blocker
Impact.MINOR // best-practice deviation with low real-world impact

Ordering: CRITICAL > SERIOUS > MODERATE > MINOR.


Scoped scans

// Scan only the login form
accessibility()
.withContext("#login-form")
.run();

// Exclude known inaccessible third-party widgets
accessibility()
.excluding("#intercom-container", "#zendesk-widget")
.run();

Collecting results without asserting

AccessibilityResult result = accessibility()
.withTags("wcag2a", "wcag21aa")
.collect();

System.out.println("Violations: " + result.violationCount());
System.out.println("Passed rules: " + result.passCount());

for (AccessibilityViolation v : result.violations()) {
System.out.println("[" + v.impact() + "] " + v.id() + " — " + v.help());
v.nodes().forEach(n -> System.out.println(" " + n.target()));
}

// Soft assertion — tolerate up to 2 minor violations
Assert.assertTrue(
result.violationsAtLevel(Impact.SERIOUS).isEmpty(),
"Serious violations found:\n" + result.violations()
);

Error message format

When .run() finds violations it throws an AssertionError with a full report:

[Accessibility] 2 violations found on: https://example.com/checkout
Rules: wcag2a, wcag21aa
Minimum impact: SERIOUS

1. [CRITICAL] image-alt
Ensures <img> elements have alternate text
Fix: Images must have alternate text
Docs: https://dequeuniversity.com/rules/axe/4.10/image-alt
→ img.hero-banner
Fix any of the following: Element does not have an alt attribute

2. [SERIOUS] color-contrast
Ensures the contrast ratio between foreground and background colors meets thresholds
Fix: Elements must have sufficient color contrast
Docs: https://dequeuniversity.com/rules/axe/4.10/color-contrast
→ p.disclaimer-text
Fix any of the following: Element has insufficient color contrast of 3.5 (Expected 4.5:1)
… and 3 more node(s)

Common WCAG tag combinations

GoalTags
WCAG 2.0 A"wcag2a"
WCAG 2.0 AA (minimum legal requirement in many countries)"wcag2a", "wcag2aa"
WCAG 2.1 AA (EU Accessibility Act, ADA)"wcag2a", "wcag21aa"
WCAG 2.2 AA"wcag2a", "wcag21aa", "wcag22aa"
Best practices (beyond WCAG)"best-practice"

Notes

  • axe-core is injected into the browser once per page load. Subsequent accessibility() calls on the same page reuse the already-injected instance.
  • No internet connection is required — axe-core 4.10.2 is bundled in the JAR as a classpath resource.
  • No extra Maven dependency is needed.