E2E testing (End-to-End) checks complete user scenarios from start to finish, covering all layers of an application: interface, business logic, network requests, and database. Unlike integration tests that verify isolated component connections, E2E tests simulate real user behavior — from opening the application to completing a target action. According to a study by Martin Fowler, 2020, E2E tests provide the highest confidence in system correctness but require careful design to avoid fragility and excessive execution time.
Key Takeaways
E2E testing (End-to-End) is a software testing method where a test executes a complete user path through all system components. A typical E2E scenario for a mobile application includes: launching the app, registering a new user, confirming email, performing the target action (placing an order, sending a message), and verifying the result in the interface. Each step uses real components — without stubs or mocks.
The main advantage of E2E tests is that they verify the system as a whole, including the interaction between the client side, server, databases, and third-party services. E2E tests detect issues that cannot be identified at lower levels of the test pyramid: data format mismatches between client and server, authorization errors in a real environment, and integration failures with payment gateways.
According to the World Quality Report 2023, teams that implemented E2E testing in their CI/CD pipeline reduce the number of critical defects at release by 45%. However, the execution time of a full E2E suite ranges from 20 minutes to 2 hours depending on the number of scenarios, which requires a well-thought-out parallel execution strategy.
The main difference lies in the scope of verification. Integration tests verify the interaction of two or three components within an application: the network layer with the repository, the database with the ViewModel. E2E tests verify the entire chain: from UI to the external backend and back. If an integration test verifies that an API request returns correct JSON, an E2E test verifies that the user sees that data on screen after the full loading cycle.
Maintenance costs also differ. Integration tests work with a controlled environment — test stubs and in-memory databases — making them stable and fast. E2E tests depend on the state of external systems, network availability, and backend versions, which increases the likelihood of false failures (flakiness). According to the Google Testing Blog (2021), E2E tests are on average 3–5 times more fragile than integration tests, requiring the implementation of retry mechanisms and stability analytics.
The choice between E2E and integration tests depends on the criticality of the scenario. Core user paths — registration, payment, account recovery — require E2E verification. Supporting scenarios — loading lists, updating a profile — can be covered by integration tests with UI checks at the individual screen level.
Not every user scenario requires an E2E test. Selection criteria include three factors: frequency of path usage, cost of failure in production, and number of systems involved. A scenario that every user performs on first launch (onboarding, registration) is an obvious candidate. An admin panel scenario accessed by 5% of users is a candidate for integration testing.
For each scenario, a minimum set of E2E tests is defined — one happy path and one error path (e.g., expired token or unavailable server). Expanding E2E coverage beyond basic scenarios should be economically justified: the ROI of E2E tests decreases after covering 10–15 key paths, as additional E2E tests do not provide proportional improvement in quality confidence.
For mobile E2E testing, there are three main categories of tools: platform-specific frameworks, cross-platform solutions, and next-generation tools. Tool selection depends on the technology stack, team qualification, and required speed of CI integration setup.
XCUITest — Apple’s native tool for iOS, part of Xcode. The most stable and performant option for iOS, providing direct access to the system’s Accessibility layer. Espresso — Google’s native framework for Android, part of AndroidX Test. For E2E scenarios, Espresso is used together with AndroidX Test Orchestrator for test isolation and preventing mutual interference. The disadvantage of platform-specific frameworks is the need to write tests separately for each platform.
Appium — a WebDriver-based tool supporting Java, Python, JavaScript, and other languages. The Appium architecture includes a server that proxies commands to platform APIs — UIAutomator for Android and XCUITest for iOS. Desired Capabilities configuration is required for each device. Detox by Wix — a framework for React Native that synchronizes with the JS thread and automatically waits for animations and network requests to complete. Detox integrates with Jest or Mocha and requires no server setup.
Maestro — a modern framework that uses YAML files to describe scenarios. Maestro requires no compilation, supports hot reload, and provides a built-in Flow Report for result analysis. The tool integrates into CI in 10 minutes and automatically synchronizes with the application state, significantly reducing test flakiness compared to Appium.
Let’s look at an E2E test for an authentication scenario in Maestro — one of the fastest-growing mobile testing tools. Maestro uses YAML format, allowing tests to be written without programming language knowledge. The second example is an E2E test in Detox for a React Native application.
The scenario describes the complete flow: opening the app, entering email and password, clicking the login button, and verifying the main screen is displayed. Maestro commands are intuitive and require no selector configuration — the framework uses element text for lookup.
# E2E: User Login
appId: com.example.myapp
---
- launchApp
- waitForVisibile:
text: "Email"
- tapOn:
text: "Email"
- inputText:
text: "user@example.com"
- tapOn:
text: "Password"
- inputText:
text: "secret123"
- tapOn:
id: "loginButton"
- waitForVisibile:
text: "Welcome back!"
- assertVisible:
text: "Welcome back!"
Detox by Wix ensures test stability through automatic synchronization with the JS thread. The test doesn’t use sleep — Detox waits for all asynchronous operations to complete before checking.
describe('Login flow', () => {
beforeEach(async () => {
await device.reloadReactNative()
})
it('should login successfully', async () => {
await expect(element(by.id('emailInput'))).toBeVisible()
await element(by.id('emailInput')).typeText('user@example.com')
await element(by.id('passwordInput')).typeText('secret123')
await element(by.id('loginButton')).tap()
await expect(element(by.text('Welcome back!'))).toBeVisible()
})
})
Integrating E2E tests into CI/CD is a key factor in their effectiveness. Recommended strategy is a two-level pipeline: on every pull request, a minimal smoke suite of 3–5 critical E2E scenarios is run, and the full regression suite runs nightly (nightly build) or before a release. This approach balances feedback speed and verification depth.
Three aspects are critical for E2E tests in CI: parallelization — running tests on multiple devices simultaneously via Firebase Test Lab or AWS Device Farm reduces execution time from hours to minutes; environment containerization — using Docker for the backend and test server ensures reproducibility; reporting and retries — automatic restart of failed tests (up to 2 attempts) and HTML report generation with video of each scenario execution.
According to the Google Testing Blog (2022), teams using a dedicated E2E CI pipeline with parallel execution reduce regression detection time by 60%. The key metric for E2E test effectiveness is not the number of tests, but the percentage of successful CI runs without false failures. The target indicator is E2E suite stability above 95% with full coverage of critical paths.
Frequently Asked Questions
For an average application, 15–25 E2E tests covering critical user scenarios are sufficient. The optimal number is determined by the test pyramid: E2E tests make up 5–10% of the total test suite. Increasing the E2E share beyond 10% leads to disproportionate growth in execution time and maintenance costs.
Use automatic retries (2–3 attempts), isolate the test environment via Docker, disable animations on the emulator, and use waitForVisible instead of fixed pauses. Tools like Detox and Maestro have built-in synchronization that significantly reduces flakiness compared to Appium.
The ideal environment for E2E tests is a staging server identical to production with test data. If staging is unavailable, use a containerized backend in Docker. A real production server must not be used for E2E tests — tests would create inconsistent data and affect real users.
Yes, native E2E tests use XCUITest (Swift) for iOS and Espresso with AndroidX Test (Kotlin) for Android. These frameworks offer better performance but do not support cross-platform testing. Appium and Maestro remain the choice for teams needing a single language for both platforms.
E2E tests are updated with every change to the user scenario: adding a new screen to the flow, changing UI elements, or navigation logic. It is recommended to conduct a test suite audit every sprint, removing outdated scenarios and adding new ones to keep the suite reflecting the current state of the application.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also