Test Example in Python

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard
Not for use with personal data

Be sure to check out the full Appium setup guide with axe DevTools Mobile if you're just getting started, or more examples of axe DevTools Mobile for Appium in other languages.

Full Example with UIAutomator2

import pytest
from appium import webdriver
from appium.options.android import UiAutomator2Options


class TestAndroidAxe:
    driver = None

    # The axe_settings object still accepts apiKey and axeServiceUrl but is not required
    # if you are going to make one time setup_class call to 'mobile: axeStartSession'
    axe_settings = {
        'tags': ['appium', 'qa'],
        'uploadToDashboard': True,
        'ignoreRules': ['ScreenOrientation']
    }
    api_key = '<YOUR_API_KEY>'
    project_id = '<YOUR_DEV_HUB_PROJECT_ID>'
    app_package = '<YOUR_APP_PACKAGE_NAME>'

    @classmethod
    def setup_class(cls):
        """
        It is very important to make a call to 'mobile: axeStartSession' inside setup_class
        to setup your session for posting to Dev Hub.
        """
        options = UiAutomator2Options()
        options.platform_name = 'Android'
        options.device_name = 'Android'
        options.app_package = cls.app_package
        options.app_activity = '.MainActivity'
        options.automation_name = 'AxeUiAutomator2'
        options.uiautomator2_server_launch_timeout = 60000
        options.uiautomator2_server_install_timeout = 60000
        options.adb_exec_timeout = 60000
        options.set_capability('ignoreHiddenApiPolicyError', True)
        options.set_capability('disableWindowAnimation', True)
        options.set_capability('waitForIdle', True)
        options.set_capability('commandTimeout', 300)
        options.no_reset = False
        options.full_reset = False

        cls.driver = webdriver.Remote(
            command_executor='http://localhost:4723',
            options=options
        )

        # Make one time call to setup your session for posting to Dev Hub.
        # This also accepts axeServiceUrl in case of private instance.
        axe_auth_settings = {
            'apiKey': cls.api_key,
            'projectId': cls.project_id
        }
        cls.driver.execute_script('mobile: axeStartSession', axe_auth_settings)

    @classmethod
    def teardown_class(cls):
        if cls.driver:
            cls.driver.quit()

    def dismiss_system_ui_error(self):
        """Dismiss System UI error popup if it appears"""
        try:
            system_popup = self.driver.find_element(
                by='xpath',
                value='//*[contains(@text, "System UI")]'
            )
            system_popup.is_displayed()

            wait_button = self.driver.find_element(
                by='xpath',
                value='//*[contains(@text, "Wait")]'
            )
            wait_button.click()
            print("Dismissed the System UI error popup by clicking 'Wait'.")
        except Exception as e:
            print('No System UI error popup appeared.')

    def launch_app(self):
        """Launch the app, handling potential System UI errors"""
        try:
            self.driver.terminate_app(self.app_package)
            self.driver.implicitly_wait(1)  # Give the app time to fully terminate
        except Exception as e:
            print(f"App was not running or failed to terminate: {str(e)}")

        self.driver.activate_app(self.app_package)

        try:
            element = self.driver.find_element(
                by='xpath',
                value='//*[contains(@text, "Screen Name")]'
            )
            # Wait for element to be displayed (timeout 30 seconds)
            from selenium.webdriver.support.ui import WebDriverWait
            from selenium.webdriver.support import expected_conditions as EC
            from appium.webdriver.common.appiumby import AppiumBy

            WebDriverWait(self.driver, 30).until(
                EC.visibility_of(element)
            )
        except Exception as e:
            self.dismiss_system_ui_error()
            # Try again after dismissing the error (if not, then fail)
            element = self.driver.find_element(
                by='xpath',
                value='//*[contains(@text, "Screen Name")]'
            )
            WebDriverWait(self.driver, 30).until(
                EC.visibility_of(element)
            )

    def setup_method(self):
        """Launch app before each test"""
        self.launch_app()

    def test_test1(self):
        """
        Now since your session is authenticated you can keep making 'mobile: axeScan' calls.
        The scans will be uploaded to the dashboard and also grouped in Dev Hub.
        """
        from selenium.webdriver.support.ui import WebDriverWait
        from selenium.webdriver.support import expected_conditions as EC

        element = self.driver.find_element(
            by='xpath',
            value='//*[contains(@text, "Screen Name")]'
        )
        WebDriverWait(self.driver, 10).until(
            EC.visibility_of(element)
        )
        print(element.text)

        appium_scan_result = self.driver.execute_script('mobile: axeScan', self.axe_settings)
        results = appium_scan_result['axeRuleResults']
        print(f'debug: Total results: {len(results)}')

    def test_test2(self):
        """Second test with interaction"""
        from selenium.webdriver.support.ui import WebDriverWait
        from selenium.webdriver.support import expected_conditions as EC

        element = self.driver.find_element(
            by='xpath',
            value='//*[contains(@text, "Screen Name")]'
        )
        WebDriverWait(self.driver, 10).until(
            EC.visibility_of(element)
        )
        element.click()

        self.driver.find_element(
            by='xpath',
            value='//*[contains(@text, "announced by a screen")]'
        )

        appium_scan_result = self.driver.execute_script('mobile: axeScan', self.axe_settings)
        results = appium_scan_result['axeRuleResults']
        print(f'debug: Total results: {len(results)}')

Full Example with XCUITest

import pytest
from appium import webdriver
from appium.options.ios import XCUITestOptions


class TestIOSMapsAxe:
    driver = None

    # The axe_settings object still accepts apiKey and axeServiceUrl but is not required
    # if you are going to make one time setup_class call to 'mobile: axeStartSession'
    axe_settings = {
        'tags': ['appium', 'qa', 'ios'],
        'uploadToDashboard': True,
        'ignoreRules': ['ScreenOrientation']
    }
    api_key = '<YOUR_API_KEY>'
    project_id = '<YOUR_DEV_HUB_PROJECT_ID>'
    bundle_id = 'com.apple.Maps'

    @classmethod
    def setup_class(cls):
        """
        It is very important to make a call to 'mobile: axeStartSession' inside setup_class
        to setup your session for posting to Dev Hub.
        """
        options = XCUITestOptions()
        options.platform_name = 'iOS'
        options.automation_name = 'AxeXCUITest'
        options.udid = '<YOUR_DEVICE_OR_SIMULATOR_UDID>'
        options.bundle_id = cls.bundle_id
        options.set_capability('wdaLaunchTimeout', 960000)  # 16 minutes
        # NOT specifying platformVersion - let it auto-detect

        cls.driver = webdriver.Remote(
            command_executor='http://127.0.0.1:4723',
            options=options
        )

        # Make one time call to setup your session for posting to Dev Hub.
        # This also accepts axeServiceUrl in case of private instance.
        axe_auth_settings = {
            'apiKey': cls.api_key,
            'projectId': cls.project_id,
            'axeServiceUrl': 'https://mobile-qa.dequelabs.com'
        }
        cls.driver.execute_script('mobile: axeStartSession', axe_auth_settings)

    @classmethod
    def teardown_class(cls):
        if cls.driver:
            cls.driver.implicitly_wait(1)
            cls.driver.quit()

    def launch_app(self):
        """Launch the Maps app"""
        self.driver.activate_app(self.bundle_id)

    def setup_method(self):
        """Launch app before each test"""
        self.launch_app()

    def test_test1_scan_main_screen(self):
        """
        Now since your session is authenticated you can keep making 'mobile: axeScan' calls.
        The scans will be uploaded to the dashboard and also grouped in Dev Hub.
        """
        appium_scan_result = self.driver.execute_script('mobile: axeScan', self.axe_settings)
        results = appium_scan_result['axeRuleResults']
        print(f'debug: Total results: {len(results)}')

    def test_test2_click_search_and_scan(self):
        """Second test - click search and scan"""
        appium_scan_result = self.driver.execute_script('mobile: axeScan', self.axe_settings)
        results = appium_scan_result['axeRuleResults']
        print(f'debug: Total results: {len(results)}')