Skip to content
Go back

Test Automation - How To Perform Automated Accessibility Checks Using Playwright Python And Axe

Published:

Introduction

In today’s digital landscape, ensuring web accessibility is not just a moral obligation but a crucial aspect of delivering inclusive experiences to users with diverse needs. Playwright, a powerful browser automation tool, coupled with the Axe accessibility testing library, provides a robust solution for automating accessibility checks during your testing pipeline. By integrating these two powerful tools, you can proactively identify and address accessibility issues.

The solution presented in this article is exemplified in my Playwright Python example project, developed in collaboration with Elias Shourosh.

Implementing the Solution

The AxeHelper class contains the check_accessibility the method that runs Axe on a given Playwright page, checks for accessibility violations based on the specified maximum allowed violations per impact level, and provides detailed reporting.

The solution code can be found here.

import json from collections import Counter from typing import Dict  import allure from axe_playwright_python.sync_playwright import Axe from playwright.sync_api import Page  class AxeHelper:   def __init__(self, axe: Axe):  self.axe = axe   def check_accessibility(  self, page: Page, maximum_allowed_violation_by_impact: Dict[str, int] = None  ) -> None:  """Checks accessibility of the page using playwright axe.   :param page: Playwright Page object  :param maximum_allowed_violations_by_impact: A dictionary  specifying the maximum allowed violations for each impact  level (e.g., {'minor': 2, 'moderate': 1, 'serious': 0, 'critical': 0}). If None, no violations will be allowed for  any impact level.  """  if maximum_allowed_violation_by_impact is None:  maximum_allowed_violation_by_impact = {  "minor": 0,  "moderate": 0,  "serious": 0,  "critical": 0,  }  results = self.axe.run(page)  violations_count = dict(  Counter(  [violation["impact"] for violation in results.response["violations"]]  )  )  if violations_exceeded := {  impact_level: violation_count  for impact_level, violation_count in violations_count.items()  if violation_count  > maximum_allowed_violation_by_impact.get(impact_level, 0)  }:  allure.attach(  body=json.dumps(results.response["violations"], indent=4),  name="Accessibility Violation Results",  attachment_type=allure.attachment_type.JSON,  )  assert not violations_exceeded, (  f"Found accessibility violations exceeding the maximum allowed: "  f"{violations_exceeded}"  )

The conftest file defines a pytest fixture that creates an instance of AxeHelper with Axe initialized. This fixture has a session scope, meaning it’s created once per test session and shared across all tests.

import pytest from axe_playwright_python.sync_playwright import Axe  from utilities.axe_helper import AxeHelper  @pytest.fixture(scope="session") def axe_playwright():  """Fixture to provide an instance of AxeHelper with Axe initialized.   This fixture has a session scope, meaning it will be created once per test session  and shared across all tests.   Returns:  AxeHelper: An instance of AxeHelper with Axe initialized.  """  yield AxeHelper(Axe())

Test Usage

The test usage can be found here.

import allure  class TestAccessibility:   @allure.title("Test Accessibility with Default Counts")  def test_accessibility_default_counts(self, axe_playwright, page):  axe_playwright.check_accessibility(page)   @allure.title("Test Accessibility with Custom Counts")  def test_accessibility_custom_counts(self, axe_playwright, page):  axe_playwright.check_accessibility(  page,  maximum_allowed_violation_by_impact={  "minor": 2,  "moderate": 5,  "serious": 0,  "critical": 0,  },  )

The first test, test_accessibility_default_counts, invokes the check_accessibility method of the axe_playwright fixture, which scans the given page for accessibility violations, allowing no violations of any impact level. The second test, test_accessibility_custom_counts, demonstrates how to customize the maximum allowed violations per impact level using the maximum_allowed_violations_by_impact parameter.

In conclusion

Integrating Axe with Playwright empowers automation engineers to incorporate accessibility testing into their workflows seamlessly.

Happy testing!


Suggest Changes

Ready to build your quality roadmap? Start Here


Previous Post
Test Automation - How to Bypass Re-Login With Playwright Python And Pytest
Next Post
Test Automation - How To Link Playwright Traces and Videos to Allure Report using GitHub Actions