Detox

repository·master·Indexed 11 days ago

https://github.com/wix/detox

A gray box end-to-end testing and automation framework for mobile applications, specifically optimized for React Native. Detox reduces test flakiness by synchronizing with the application's internal asynchronous state. It supports both Android and iOS, integrates with Jest, and provides a modern async-await API for interacting with UI components.

Tokens
98.9K
Snippets
332
Records
423
Agent score
93%

What's inside Detox

  1. What is Detox and how does it work?

    master

    Detox is a gray box end-to-end (E2E) testing and automation framework for mobile apps. Unlike black box testing, Detox uses a gray box approach to monitor asynchronous operations within your app, which helps eliminate test flakiness by automatically synchronizing with the app's state.

    Key features include:

    • Cross Platform: Write tests in JavaScript for both Android and iOS (React Native).
    • Debuggable: Uses a modern async-await API that supports breakpoints.
    • Automatically Synchronized: Monitors async operations to reduce flakiness.
    • Made For CI: Designed to run on CI platforms like Travis CI, Circle CI, or Jenkins.
    • Test Runner Agnostic: Can be used with any test runner, with built-in integration for Jest.
  2. Overview of Detox

    master
    Detox is an open-source end-to-end (E2E) testing framework designed for React Native mobile applications. It aims to enable testing of any end-to-end flow with high velocity and minimal flakiness. Detox operates by running tests on a real device or simulator, simulating actual user interactions.
  3. Understand the Artifacts Lifecycle Flow

    master

    Artifacts are managed through a specific lifecycle tied to the test suite and individual tests:

    1. Test Suite Starts: onRunDescribeStart(suite) is called.
    2. Per Test Lifecycle:
      • onTestStart(testSummary): Plugins can perform setup or take initial snapshots.
      • [Test executes]
      • Failure Handling: If a test or hook fails, onHookFailure() or onTestFnFailure() is triggered.
      • onTestDone(testSummary): Plugins perform cleanup, stop recordings, or save/discard artifacts based on the test result.
    3. Test Suite Ends: onRunDescribeFinish(suite) is called.
    4. Cleanup: onBeforeCleanup() is called, followed by final artifact processing.
  4. How the Detox Artifacts System works

    master

    The Artifacts subsystem is responsible for collecting test artifacts such as screenshots, videos, logs, and performance data during test execution.

    It is orchestrated by the ArtifactsManager, which performs the following roles:

    • Plugin Registration: Loads and instantiates various artifact plugins (e.g., Screenshot, Video, Log).
    • Event Subscription: Listens to device events (like bootDevice, launchApp, terminateApp) and test lifecycle events.
    • Lifecycle Orchestration: Triggers plugin hooks at specific stages of the test suite (e.g., onTestStart, onTestDone, onTestFnFailure).
    • Path Management: Uses ArtifactPathBuilder to generate consistent file paths following the pattern: artifacts/{config}/{test}/artifact.
    • Execution Strategy: Manages the order in which plugins are called (ascending, descending, or plain) based on their priority.

    Plugins can also request an idleCallback to defer heavy operations until the manager is idle, preventing interference with test execution timing.

    // Conceptual architecture overview
    // ArtifactsManager
    //  ├── Registers plugins
    //  ├── Subscribes to device events
    //  ├── Orchestrates lifecycle callbacks
    //  └── Manages idle callback queue
    //
    //  ├── Screenshot Plugin
    //  ├── Video Plugin
    //  ├── Log Plugin
    //  ├── Instruments Plugin
    //  └── UIHierarchy Plugin (iOS only)
  5. Limitation: shutdownDevice cannot be disabled for Genymotion SaaS

    master

    When using Genymotion SaaS, the Detox behavior.shutdownDevice property and the CLI --cleanup (-u) flag cannot be disabled.

    Detox will always shut down Genymotion SaaS devices at the end of a test session. This means you cannot keep a pool of warm, immediately ready devices running after your tests finish. However, this also prevents you from accidentally leaving devices running and incurring costs.

  6. How Detox Copilot works

    master

    Detox Copilot acts as a bridge between natural language instructions and concrete Detox actions through a multi-step execution flow:

    1. Gather Context: Collects the current app state, view hierarchy, and results from previous steps.
    2. Interpret Intent: Uses an LLM to understand the meaning of the natural language instruction.
    3. Generate Code: Translates the interpreted intent into valid Detox commands.
    4. Execute Action: Runs the generated Detox code against the application.
    5. Cache Results: Stores execution results to optimize subsequent runs.
    6. Provide Feedback: Returns values or confirms actions to inform the next step in the sequence.
  7. Manage concurrent events using event metadata IDs

    master

    When running concurrent asynchronous operations, overlapping duration events can cause visual errors on the timeline (where an event appears to end before its parent).

    To prevent this, assign a unique id (string or number) to the metadata of your events. When the logger detects an event with an id while another duration event is active, it allocates a new 'lane' (using a distinct tid) to ensure the timeline correctly represents the hierarchy.

    // Using IDs prevents overlapping events from corrupting the timeline hierarchy
    await Promise.all([
      await log.info.complete({ id: 1 }, 'Do this', async () => { /* ... */ }),
      await log.info.complete({ id: 2 }, 'Do that', async () => { /* ... */ }),
    ]);
  8. How Detox manages execution contexts with Realms

    master

    Detox uses a "realm" pattern to manage different execution contexts via the DetoxContext base class. The base class exposes the primary testing APIs: device, element, expect, by, waitFor, web, and system.

    There are two main types of realms:

    • Primary Realm (DetoxPrimaryContext): A full-featured context used in the test runner process. It handles device allocation, server lifecycle, and initialization.
    • Secondary Realm (DetoxSecondaryContext): A lightweight context used for worker processes. It contains a configuration snapshot but does not handle device management.
  9. Use Detox REPL mode for interactive debugging

    master

    Detox supports an interactive REPL (Read-Eval-Print Loop) mode. This allows you to explore the app state, issue commands, or pause test execution in real time during a test run.

    To use it:

    1. Enable the mode via the --repl CLI argument.
    2. Add await detox.REPL() at the specific point in your test code where you want the execution to pause and enter the interactive loop.
    // In your test file
    await detox.REPL();
  10. Understand the Detox framework cache structure

    master

    Detox stores cached versions of its framework and XCUITest-runner in ~/Library/Detox/ios/*. The folders are named using a hash of the specific Xcode and Detox version combination to ensure compatibility.

    This structure allows Detox to quickly locate the correct pre-built binaries for your current environment.

    ├── ios
    │   ├── framework
    │   │   ├── 197a0586bd006583562a5916c969d158133a8c50
    │   │   ├── …
    │   │   └── eddcc1edeffdb3533a977b73b667e1b7f106c38f
    │   ├── xcuitest-runner
    │   |   ├── 197a0586bd006583562a5916c969d158133a8c50
    │   |   ├── …
    │   |   └── eddcc1edeffdb3533a977b73b667e1b7f106c38f
    │…
  11. Testing strategy for Generation

    master

    The generation package uses a multi-layered testing approach:

    • Integration Tests: Uses a generated Objective-C fixture file that is imported before tests run to ensure the generated code works with the specified interface.
    • Unit Tests: Applied only to production code, such as helper functions.
    • Snapshot Tests: Used as the primary method to detect mistakes in function return values without over-specifying the expected output.
    • End-to-End (E2E) Tests: If you add functionality that modifies the Detox API surface, you must also include E2E tests located in ../detox/test/e2e.