How to Automate Nested Navigation Testing (Step-by-Step)

Automating nested navigation testing is crucial for ensuring the reliability and usability of complex applications. Nested navigation involves multiple levels of navigation, such as menus, sub-menus,

By · February 06, 2026 · 17 min read · How-To Guides

How to Automate Nested Navigation Testing (Step-by-Step)

Automating nested navigation testing is crucial for ensuring the reliability and usability of complex applications. Nested navigation involves multiple levels of navigation, such as menus, sub-menus, tabs, and modals, which can be challenging to test manually due to the sheer number of paths and interactions. This guide will walk you through the process step-by-step, covering when automation pays off, choosing the right framework, writing stable and maintainable tests, locator strategies, handling waits and flake, data setup and teardown, running tests in CI, and reporting results. We'll also explore how autonomous exploration can bootstrap nested navigation automation without scripts.

When to Automate Nested Navigation Testing

Identifying the Need for Automation

Before diving into automation, it's important to identify when it makes sense to automate nested navigation testing. Here are some scenarios where automation is particularly beneficial:

When Not to Automate

While automation is powerful, it's not always the best solution. Here are some scenarios where manual testing might be more appropriate:

Choosing the Right Framework

Popular Frameworks for Nested Navigation Testing

Choosing the right framework is crucial for the success of your automation efforts. Here are some popular frameworks and their pros and cons:

FrameworkLanguageProsCons
AppiumJava, Python, Ruby, etc.Cross-platform support, extensive community, robust capabilitiesSetup can be complex, performance issues with mobile web testing
PlaywrightJavaScript, TypeScriptCross-platform, fast, easy to use, built-in tracing and video recordingLimited community support compared to Appium, primarily web-focused
SeleniumJava, Python, Ruby, etc.Mature, extensive ecosystem, widely used in the industryCan be slow, requires robust setup for mobile testing
CypressJavaScriptFast, easy to set up, excellent documentation and community supportWeb-only, limited mobile support
SUSAPythonAutonomous exploration, no scripts needed, cross-session learningLess control over specific test cases, might miss edge cases

Factors to Consider

Writing Stable and Maintainable Tests

Best Practices for Test Writing

Writing stable and maintainable tests is essential for the long-term success of your automation efforts. Here are some best practices to follow:

Example: Page Object Model in Appium

Here's an example of how to implement the Page Object Model in Appium for nested navigation testing:


from appium import webdriver
from selenium.webdriver.common.by import By

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.username_input = (By.ID, 'username')
        self.password_input = (By.ID, 'password')
        self.login_button = (By.ID, 'loginButton')

    def login(self, username, password):
        self.driver.find_element(*self.username_input).send_keys(username)
        self.driver.find_element(*self.password_input).send_keys(password)
        self.driver.find_element(*self.login_button).click()

class DashboardPage:
    def __init__(self, driver):
        self.driver = driver
        self.menu_button = (By.ID, 'menuButton')

    def navigate_to_menu(self):
        self.driver.find_element(*self.menu_button).click()

class MenuPage:
    def __init__(self, driver):
        self.driver = driver
        self.sub_menu_button = (By.ID, 'subMenuButton')

    def navigate_to_sub_menu(self):
        self.driver.find_element(*self.sub_menu_button).click()

def test_nested_navigation():
    desired_caps = {
        'platformName': 'Android',
        'deviceName': 'Android Emulator',
        'app': 'path/to/your/app.apk'
    }
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    login_page = LoginPage(driver)
    login_page.login('user', 'password')

    dashboard_page = DashboardPage(driver)
    dashboard_page.navigate_to_menu()

    menu_page = MenuPage(driver)
    menu_page.navigate_to_sub_menu()

    driver.quit()

Locator Strategy

Choosing the Right Locators

The choice of locators can significantly impact the stability and maintainability of your tests. Here are some strategies to consider:

Handling Dynamic Elements

Dynamic elements, such as those generated by JavaScript or those that change based on user interactions, can be challenging to locate. Here are some strategies to handle dynamic elements:

Example: Handling Dynamic Elements in Playwright

Here's an example of how to handle dynamic elements in Playwright:


const { test, expect } = require('@playwright/test');

test('nested navigation with dynamic elements', async ({ page }) => {
  // Navigate to the login page
  await page.goto('https://example.com/login');

  // Wait for the username input to be visible and enter the username
  await page.waitForSelector('#username');
  await page.fill('#username', 'user');

  // Wait for the password input to be visible and enter the password
  await page.waitForSelector('#password');
  await page.fill('#password', 'password');

  // Click the login button
  await page.click('#loginButton');

  // Wait for the dashboard page to load
  await page.waitForSelector('#menuButton');

  // Click the menu button
  await page.click('#menuButton');

  // Wait for the sub-menu button to be visible and click it
  await page.waitForSelector('#subMenuButton');
  await page.click('#subMenuButton');

  // Verify the sub-menu page is loaded
  await expect(page).toHaveURL('https://example.com/sub-menu');
});

Handling Waits and Flake

Understanding Waits

Waits are essential for ensuring that elements are present and interactable before performing actions. There are two types of waits:

Best Practices for Waits

Handling Flake

Flaky tests are tests that pass or fail non-deterministically. They can be frustrating and reduce confidence in the test suite. Here are some strategies to handle flaky tests:

Example: Handling Waits in Appium

Here's an example of how to handle waits in Appium:


from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

desired_caps = {
    'platformName': 'Android',
    'deviceName': 'Android Emulator',
    'app': 'path/to/your/app.apk'
}
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

# Wait for the login page to load
wait = WebDriverWait(driver, 10)
login_page = wait.until(EC.presence_of_element_located((By.ID, 'loginButton')))

# Click the login button
login_page.click()

# Wait for the dashboard page to load
wait.until(EC.presence_of_element_located((By.ID, 'menuButton')))

# Click the menu button
driver.find_element(By.ID, 'menuButton').click()

# Wait for the sub-menu page to load
wait.until(EC.presence_of_element_located((By.ID, 'subMenuButton')))

# Click the sub-menu button
driver.find_element(By.ID, 'subMenuButton').click()

driver.quit()

Data Setup and Teardown

Setting Up Test Data

Setting up test data is crucial for ensuring that tests run consistently and produce reliable results. Here are some strategies for setting up test data:

Teardown and Cleanup

Cleaning up after tests is just as important as setting up test data. Here are some strategies for teardown and cleanup:

Example: Data Setup and Teardown in Python

Here's an example of how to set up and tear down test data in Python:


import unittest
from faker import Faker
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class NestedNavigationTest(unittest.TestCase):
    def setUp(self):
        self.desired_caps = {
            'platformName': 'Android',
            'deviceName': 'Android Emulator',
            'app': 'path/to/your/app.apk'
        }
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', self.desired_caps)
        self.faker = Faker()

    def tearDown(self):
        self.driver.quit()

    def test_nested_navigation(self):
        # Generate dynamic test data
        username = self.faker.user_name()
        password = self.faker.password()

        # Wait for the login page to load
        wait = WebDriverWait(self.driver, 10)
        login_page = wait.until(EC.presence_of_element_located((By.ID, 'loginButton')))

        # Enter the username and password
        self.driver.find_element(By.ID, 'username').send_keys(username)
        self.driver.find_element(By.ID, 'password').send_keys(password)

        # Click the login button
        login_page.click()

        # Wait for the dashboard page to load
        wait.until(EC.presence_of_element_located((By.ID, 'menuButton')))

        # Click the menu button
        self.driver.find_element(By.ID, 'menuButton').click()

        # Wait for the sub-menu page to load
        wait.until(EC.presence_of_element_located((By.ID, 'subMenuButton')))

        # Click the sub-menu button
        self.driver.find_element(By.ID, 'subMenuButton').click()

if __name__ == '__main__':
    unittest.main()

Running Tests in CI

Integrating with CI/CD Pipelines

Integrating automated tests into your CI/CD pipeline is essential for ensuring that your application remains reliable and maintainable. Here are some best practices for integrating tests into CI/CD:

Example: Running Tests in Jenkins

Here's an example of how to run automated tests in Jenkins:

  1. Install the necessary plugins: Install the Appium and TestNG plugins in Jenkins.
  2. Create a new Jenkins job: Create a new job for running your automated tests.
  3. Configure the build steps:
  1. Configure notifications: Set up notifications to alert you when tests fail.

Example: Jenkinsfile for Running Tests

Here's an example of a Jenkinsfile for running automated tests:


pipeline {
    agent any

    stages {
        stage('Start Appium Server') {
            steps {
                sh 'appium &'
            }
        }

        stage('Run Tests') {
            steps {
                sh 'python -m unittest discover -s tests'
            }
        }

        stage('Generate Test Reports') {
            steps {
                sh 'allure generate allure-results -o allure-report --clean'
            }
        }

        stage('Stop Appium Server') {
            steps {
                sh 'pkill -f appium'
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: 'allure-report/**', allowEmptyArchive: true
            allure includeProperties: false, jdk: '', results: [[path: 'allure-results']]
            mail to: 'team@example.com', subject: 'Test Results', body: 'Please check the test results in the allure report.'
        }
    }
}

Reporting and Analysis

Generating Test Reports

Generating detailed test reports is crucial for understanding the results of your tests and identifying areas for improvement. Here are some tools and techniques for generating test reports:

Analyzing Test Results

Analyzing test results is essential for identifying trends, understanding the root causes of failures, and making data-driven decisions. Here are some strategies for analyzing test results:

Example: Generating Allure Reports

Here's an example of how to generate Allure reports using Python and the Allure-Pytest plugin:

  1. Install the Allure-Pytest plugin:
  2. 
       pip install allure-pytest
    
  1. Run tests with Allure:
  2. 
       pytest --alluredir=allure-results
    
  1. Generate the Allure report:
  2. 
       allure generate allure-results -o allure-report --clean
    
  1. Serve the Allure report:
  2. 
       allure serve allure-report
    

Bootstrapping Nested Navigation Automation with Autonomous Exploration

Introduction to Autonomous Exploration

Autonomous exploration is a powerful technique for automating nested navigation testing without writing scripts. Tools like SUSA can explore the application, tap, scroll, type, and handle dialogs, completing real flows and identifying issues such as crashes, ANRs, dead buttons, accessibility violations, security issues, and UX friction.

How SUSA Works

SUSA works by:

Example: Using SUSA for Nested Navigation Testing

Here's an example of how to use SUSA for nested navigation testing:

  1. Install the SUSA CLI:
  2. 
       pip install susatest-agent
    
  1. Run SUSA on an APK :
  2. 
    susatest-agent test path/to/your/app.apk
    
  1. Run SUSA on a Web URL :
  2. 
    susatest-agent test https://example.com
    
  1. View the Results :

SUSA provides a detailed report of the issues it found, including crashes, ANRs, dead buttons, accessibility violations, security issues, and UX friction.

  1. Generate Regression Scripts:

SUSA can auto-generate regression scripts from the discovered flows, which you can use for ongoing testing.

Nested Navigation Test Matrix

Creating a Test Matrix

A test matrix is a table that helps you organize and manage your test cases. It ensures that all critical paths and edge cases are covered. Here's an example of a nested navigation test matrix:

Test Case IDDescriptionSteps to ReproduceExpected ResultActual ResultStatus
001Login and navigate to dashboard1. Open the app. 2. Click the login button. 3. Enter valid credentials. 4. Click login.Dashboard page should load successfully.Dashboard page loads.Pass
002Navigate to sub-menu from dashboard1. From the dashboard, click the menu button. 2. Click the sub-menu button.Sub-menu page should load successfully.Sub-menu page loads.Pass
003Navigate to sub-menu from login page1. From the login page, click the menu button. 2. Click the sub-menu button.Sub-menu page should load successfully.Sub-menu page loads.Pass
004Navigate to sub-menu with invalid credentials1. From the login page, click the menu button. 2. Click the sub-menu button. 3. Enter invalid credentials. 4. Click login.Error message should be displayed.Error message displayed.Pass
005Navigate to sub-menu with no credentials1. From the login page, click the menu button. 2. Click the sub-menu button. 3. Click login without entering credentials.Error message should be displayed.Error message displayed.Pass
006Navigate to sub-menu after session timeout1. From the dashboard, wait for the session to timeout. 2. Click the menu button. 3. Click the sub-menu button.Login page should be displayed.Login page displayed.Pass
007Navigate to sub-menu with dynamic content1. From the dashboard, click the menu button. 2. Click the sub-menu button. 3. Verify dynamic content is loaded.Dynamic content should be loaded successfully.Dynamic content loaded.Pass
008Navigate to sub-menu with slow network1. From the dashboard, click the menu button. 2. Click the sub-menu button. 3. Verify the page loads with a slow network connection.Sub-menu page should load successfully.Sub-menu page loads.Pass

Edge Cases and Production Issues

Identifying Edge Cases

Edge cases are scenarios that are less common but can still cause issues in production. Here are some strategies for identifying edge cases:

Handling Production Issues

Production issues can be challenging to reproduce and fix. Here are some strategies for handling production issues:

Example: Handling a Production Issue

Here's an example of how to handle a production issue:

  1. Reproduce the Issue:
  1. Use Logs and Metrics:
  1. Rollback:
  1. Hotfix:

Checklist for Nested Navigation Testing

Pre-Test Checklist

Post-Test Checklist

Closing Takeaways

Key Points to Remember

By following these best practices, you can effectively automate nested navigation testing and ensure the reliability and usability of your complex applications.

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 11 real users — finds bugs, accessibility violations, and security issues. No scripts. New to the category? Start with what autonomous product intelligence & QA means.

Try SUSA Free