•
Drizz raises $2.7M in seed funding •
•
Featured on Forbes
•
Drizz raises $2.7M in seed funding •
•
Featured on Forbes
Logo
Schedule a demo
Blog page
>
Test fixtures: Setup Patterns for Mobile QA

Test fixtures: Setup Patterns for Mobile QA

Test fixtures explained for mobile QA teams. Setup and teardown patterns, fixture scoping, pytest fixtures, and how to manage app state across iOS and Android test runs.
Author:
Asad Abrar
Posted on:
June 22, 2026
Read time:

A test fixture is  setup your test needs before it can run. It includes  data,  app state,  device configuration, and everything else that has to be true before your first assertion. Without a reliable fixture, your test might pass on one run and fail on  next for reasons that have nothing to do with bugs.

On mobile, fixtures are harder than on web. Fixture testing involves managing app installation, login state, permission dialogs, GPS coordinates, network conditions, and platform differences between iOS and Android. Most guides on fixtures testing cover web and database patterns. This one covers what mobile QA teams actually need.

What is a test fixture?

A test fixture is  controlled environment that a test runs in. The test fixture meaning in software testing is straightforward: it's everything you set up before  test executes and everything you clean up after it finishes.

A fixture typically includes:

  • The state of  application (logged in, onboarded, specific screen loaded)
  • The test data (user accounts, products, orders that  test depends on)
  • The device or environment configuration (OS version, screen size, locale)
  • Mocks or stubs for external services (payment gateway, push notification server)

The goal is repeatability. Every time  test runs, it starts from  same state. If  fixture is inconsistent,  test becomes flaky. On mobile, fixture inconsistency is one of  top causes of test flakiness after selector breakage.

What are  common fixture test patterns?

There are three standard setup patterns for test fixtures, originally described on Wikipedia's test fixture page and used across every major testing framework:

Pattern How it works Best for
In-line setup Each test creates its own fixture data inside the test method Simple tests with unique data needs
Delegate setup A shared helper method creates fixture, called by multiple tests Tests that share similar but not identical setup
Implicit setup A setUp() method runs automatically before every test in class Tests in same class that all need same preconditions

On mobile, most teams use implicit setup for common preconditions (install app, launch, handle permissions) and delegate setup for test-specific data (create a test user with specific account settings).

In-line setup is fine for one-off tests but leads to duplication fast. If ten tests all need a logged-in user, writing  login fixture inline in each test means ten copies of  same setup code. When  login flow changes, you update all ten.

How do test fixtures work on mobile?

Mobile test fixtures handle two layers of setup that web tests don't need: app state and device state.

App state fixtures manage things like:

  • Installing or updating  app binary (APK or IPA)
  • Clearing app data between tests to start fresh
  • Completing onboarding flows so tests start from  home screen
  • Logging in with a test account
  • Setting  app to a specific state (items in cart, pending order, active subscription)

Device state fixtures manage things like:

  • Setting GPS coordinates for location-based features
  • Configuring network conditions (WiFi, cellular, airplane mode, slow network)
  • Handling system permission dialogs (camera, location, notifications)
  • Setting device locale and language
  • Managing device orientation (portrait vs landscape)

On a test automation framework like Appium, these fixtures are coded as setup and teardown methods. A session-level fixture installs  app once and keeps it running across all tests. A function-level fixture resets  app to a clean state before each individual test.

What is fixture scoping and why does it matter?

Fixture scoping controls how long a fixture lives and how many tests share it. Getting  scope right directly affects your test suite's speed and reliability.

Scope When it runs When to use Trade-off
Session Once per entire test run App installation, driver initialization Fast, but tests share state
Module/class Once per test file or class Login, navigate to a specific section Balanced speed and isolation
Function Before every individual test App data reset, unique test data creation Slow, but fully isolated

For mobile,  session scope handles  expensive operations: installing  app, launching  driver, and connecting to  device. These take seconds and shouldn't repeat for every test.

The function scope handles isolation: clearing app data, resetting to  home screen, and creating test-specific data. This ensures one test's side effects don't leak into  next test.

A common mistake on mobile teams is running everything at  function scope. Installing  app before every test adds 10 to 30 seconds per test. On a 200-test suite, that's 30 to 100 minutes of wasted time just on fixture setup.

How do pytest fixtures work for mobile testing?

Pytest fixtures are  most flexible fixture system in  Python ecosystem. They use decorators and dependency injection instead of class-based setup/teardown methods.

A pytest fixture for mobile testing might look like this:

import pytest

@pytest.fixture(scope="session")
def driver():
    """Install app and create driver once per test run."""
    d = create_appium_driver(app_path="app.apk")
    yield d
    d.quit()

@pytest.fixture(scope="function")
def logged_in_user(driver):
    """Reset app and log in before each test."""
    driver.reset()
    login_page = LoginPage(driver)
    login_page.login("testuser@email.com", "pass123")
    yield
    # teardown: nothing needed, reset handles it

‍

The session-scoped driver fixture installs  app once. The function-scoped logged_in_user fixture resets and logs in before each test. Pytest handles  dependency chain automatically.

What are pytest fixtures doing differently from JUnit or XCTest? The main difference is dependency injection. A pytest fixture can depend on another fixture. The logged_in_user fixture automatically receives  driver fixture because it declares it as a parameter. This makes fixture composition clean and avoids global state.

For teams using pytest fixtures with Appium for mobile testing, this pattern handles most fixture needs without custom framework code.

What fixture patterns reduce mobile test flakiness?

Flaky tests on mobile often trace back to fixture problems. Here are  patterns that reduce flakiness:

Reset app state between tests. Don't assume  previous test left  app in a clean state. Call driver.reset() or clear app data before each test. This adds a few seconds but eliminates state leakage between tests.

Handle permission dialogs in fixtures. iOS and Android show permission prompts (location, camera, notifications) that block test execution. Handle these in your fixture setup, not in each test. On Appium, you can use desired capabilities to auto-grant permissions. On real devices, you may need a fixture step that dismisses dialogs.

Create test data through APIs, not  UI. If your test needs a user with three items in their cart, don't walk through  UI to add items. Call your backend API to create  cart state directly. UI based data setup is slow and fragile. API-based fixtures are fast and stable.

Use factory patterns for test data. Instead of hardcoding user accounts in every test, create a UserFactory that generates test users with configurable attributes. This keeps fixture data organized and maintainable.

What does a real before and after look like?

A travel booking app team had 180 Appium tests with inconsistent fixtures. Some tests installed  app fresh. Others assumed  app was already running. Some logged in through  UI. Others used a stored auth token. Test data was hardcoded in each test file.

The result: 25% flakiness rate. Most failures were fixture-related, not actual bugs. Tests failed because  app was in  wrong state from a previous test, or because a hardcoded test account had been modified by another test running in parallel.

They restructured their fixtures:

  • Session-scoped fixture for app installation and driver setup (runs once)
  • Module-scoped fixture for login (runs once per test file, uses API-based auth)
  • Function-scoped fixture for app data reset (clears state before each test)
  • Test data factory that generates unique users and orders per test

Flakiness dropped from 25% to under 3%. The suite also got 40% faster because they stopped reinstalling  app for every test.

Teams using Drizz have simpler fixture needs because plain English tests handle app state naturally. A test that starts with "Open  app" and "Tap on Login" manages its own setup through  test steps. The fixture burden shifts from coded setup/teardown methods to clear test instructions that Drizz executes on real devices using Vision AI.

How should you structure fixtures for your mobile test suite?

Start with this three-layer fixture structure:

Scope What it handles Runs
Session App install, driver init, device connection Once per test run
Module/class Login, navigation to a specific app section Once per test file
Function App data reset, unique test data creation Before each test

Then apply these rules:

  • Expensive operations (app install, driver creation) go in session scope
  • Shared preconditions (login state) go in module scope
  • Test isolation (data reset, state cleanup) goes in function scope
  • Test data creation uses APIs, not UI interactions
  • Permission handling happens in fixtures, not in test steps

For teams building a new mobile test suite, investing in solid fixture patterns up front saves weeks of debugging flaky tests later. For teams already running a suite with flakiness problems, auditing your fixtures is  first place to look. Tools like Drizz reduce fixture complexity because Vision AI tests don't require  selector based page object setup that traditional fixtures support. The test itself becomes  fixture, describing what to do on screen in plain English.

‍

FAQs

What is a test fixture?

A test fixture is  controlled environment a test runs in, including app state, test data, device configuration, and mocks. The test fixture meaning (or test fixtures meaning in plural) is everything you set up before  test executes and clean up afterward. Good fixtures make tests repeatable and reduce flakiness.

What are test fixtures in mobile testing?

In mobile testing, fixtures handle two layers: app state (installation, login, data setup) and device state (GPS, network, permissions, locale). Mobile fixtures are more complex than web fixtures because they manage both  application and  physical device.

What is a software test fixture example?

A software test fixture example for mobile: a session-scoped fixture installs  app and creates  driver once. A function-scoped fixture resets app data and logs in with a test account before each test. This gives every test a clean, logged-in state without reinstalling  app.

What are pytest fixtures and how do they work?

So what is pytest fixture? Pytest fixtures use decorators and dependency injection to manage test setup. You define a fixture function with @pytest.fixture(scope="session") or @pytest.fixture(scope="function") and pytest automatically runs it before matching tests. Fixtures can depend on other fixtures, creating composable setup chains.

How do test fixtures reduce flakiness?

Fixtures reduce flakiness by ensuring every test starts from  same state. Resetting app data between tests prevents state leakage. Creating test data through APIs instead of UI interactions makes setup faster and more reliable. Handling permission dialogs in fixtures prevents random blocks during test execution.

What is  difference between setup and teardown in fixtures?

Setup runs before  test and creates  preconditions (install app, log in, create data). Teardown runs after  test and cleans up (close driver, delete test data, reset state). Most fixture frameworks handle both through setUp()/tearDown() methods or through yield-based patterns like pytest's yield keyword.

‍

About the Author:

Asad Abrar
Co-founder & CEO, Drizz
Ex-Coinbase PM and IIT Kharagpur grad killing flaky mobile tests by day, and obsessing over F1 lap timings by night.
Schedule a demo