Skip to main content

Command Palette

Search for a command to run...

📚 Android Studio Journeys: From Demo to Enterprise-Scale Testing —Part 1

Journeys 101: What, Why, and When to Use Them

Published
14 min read
📚 Android Studio Journeys: From Demo to Enterprise-Scale Testing —Part 1

End-to-end (E2E) testing is a cornerstone of delivering high-quality mobile applications. However, as apps grow in complexity and teams scale, the cost, time, and flakiness associated with traditional E2E tests can become significant hurdles. Android Studio Journeys, powered by Gemini, offer a fresh perspective on tackling these challenges.

This article lays the foundation: we'll explore what Journeys are, how they compare to familiar tools like Espresso and Compose UI tests, why they're a promising development for E2E testing, their current limitations, and how you can write your very first Journey.

Audience Takeaway: By the end of this post, you'll understand what Journeys are, their primary strengths and weaknesses, and how to start experimenting with them safely and effectively in your projects.


What Exactly Are Android Studio Journeys?

Journeys are a new experimental feature in Android Studio that let you describe end-to-end user flows in natural language (NL), while the IDE (powered by Gemini) translates those flows into executable UI actions.

At their core, Android Studio Journeys allow you to define user-like interactions and verifications using natural language. Instead of writing detailed programmatic steps, you describe a user's path through your app in plain English.

The Anatomy of a Journey:

  1. A journey file (usually .journey) describes a user flow in a natural Language input: You start by providing a description of the user flow. For example: "Launch the app. Check that a grid of images is visible. Tap the first image. Verify that a screen with image details is now shown."

  2. Gemini's Role in Interpretation: Android Studio leverages sophisticated AI, including Gemini, to understand your natural language input. It parses your instructions and translates them into a sequence of concrete UI interactions (like taps, scrolls, text inputs) and assertions (like checking if a view is displayed or contains specific text).

  3. Executable Test Actions: This interpreted sequence becomes a set of executable steps that Android Studio can run on a connected device or emulator, much like a traditional UI test. The Journey tooling handles the interaction with your app's UI layer based on the AI's interpretation.

Think of it as having an AI assistant that understands how users interact with apps and can translate your high-level descriptions into automated test scripts. This aims to simplify test creation and make it more accessible.

Example snippet:

Journey: Login flow
- Open the app
- Tap on "Login"
- Enter "test@example.com" into the email field
- Enter "password123" into the password field
- Tap on "Sign In"
- Verify that the Home screen is displayed

Journeys bridge the gap between QA-friendly specs (“verify login works”) and executable UI tests.


How Do Journeys Differ from Espresso or Compose UI Tests?

Journeys aren't here to wholesale replace established frameworks like Espresso (for View-based UIs) or Compose UI tests. Instead, they offer a different approach with its own set of trade-offs:

FeatureAndroid Studio JourneysEspresso / Compose UI Tests
AuthoringNatural Language (e.g., English descriptions)Kotlin/Java code
Primary FocusHigh-level, end-to-end "happy path" user flowsMicro interaction (animations, gestures). Detailed component interactions, edge cases (network failure, locale switching), and specific states
Barrier to EntryLower; potentially accessible to non-programmersHigher; requires programming knowledge
GranularityCoarser-grained; focuses on the overall flowFine-grained control over individual interactions/assertions
MaintenanceEdit Natural Language; stability depends on AI and stable selectorsDirect code changes; refactoring tools can help
DeterminismRelies on AI interpretation and implicit synchronizationExplicit control via Idling Resources, precise matchers
DebuggingInterpret Natural Language vs. generated actions; evolving toolsStandard code debugging tools and practices

Key Differences Summarized:

  • Authoring Experience: Journeys prioritize ease of expression through natural language. Espresso/Compose demands coding proficiency but offers precision

  • Best For: Journeys are initially best suited for validating critical user paths and high-level flows. Espresso/Compose excel at intricate UI logic, specific state validations, and complex test scenarios

  • Control vs. Convenience: Journeys trade some of the explicit control of programmatic tests for the convenience of natural language authoring

The right approach isn’t Journeys vs Espresso vs Unit Tests — it’s Journeys + Espresso + Unit Tests, each at the right level.


Why Do Journeys Matter? The Promise of Lower-Cost E2E Testing

The "cost" of testing isn't just about monetary expense; it's also about time, effort, and maintainability. Here's where Journeys aims to make a difference, especially in large, complex applications:

  1. Increased Speed of Creation (for certain tests): Describing a straightforward user flow in English can be significantly faster than writing the equivalent Espresso or Compose UI test code, especially for those less familiar with testing APIs.

  2. Broader Accessibility: Journeys can potentially empower more team members to contribute to E2E testing. Product managers, designers, and QA engineers could (with guidance and clear conventions) define or review Journeys, fostering a shared understanding of user flows.

  3. Focus on User Experience: By defining tests based on user goals and narratives, teams naturally keep the user experience at the forefront.

  4. Reduced Boilerplate (Potentially): The AI handles the translation from natural language to actions, which can reduce the amount of repetitive boilerplate code often associated with UI tests (e.g., finding views, performing clicks, basic assertions).

  5. Encouraging Best Practices from the Start:

    • Clear Intent: Writing a Journey forces you to articulate the user's path and expected outcomes clearly.

    • Rapid Coverage of Critical Paths: Teams can quickly establish baseline E2E coverage for their most important user flows. This frees up developer and QA time to write more targeted Espresso/Compose tests for complex logic, error conditions, and edge cases.

In an enterprise setting with millions of users and large development teams, the ability to quickly define and maintain tests for core functionality can significantly improve development velocity and confidence.


Navigating the New Terrain: Current Limitations of Journeys

As with any innovative technology, especially one leveraging AI, it's crucial to understand the current limitations:

  1. Early Stage Technology: Journeys are relatively new. The tooling, AI understanding, and feature set are continuously evolving. Expect rapid improvements but also potential rough edges. Journeys are still evolving; APIs and tooling may change.

  2. AI Interpretation Nuances: Natural language can be ambiguous. The AI might not always interpret your intent perfectly on the first try, requiring you to rephrase or iterate on your descriptions. What's "obvious" to a human might need more explicit instruction for the AI.

  3. Not a replacement for Espresso: Use Journeys for flows, not precision.

  4. Complex Logic and Edge Cases: Journeys are currently best suited for more linear, "happy path" scenarios. They might struggle with:

    • Highly conditional flows with many branches

    • Intricate data validation beyond simple presence or text checks

    • Testing specific error states or unusual UI conditions that require precise setup

  5. Synchronization and Flakiness: All UI tests are susceptible to flakiness (tests failing intermittently due to timing issues, animations, network delays, etc.). While Journeys aim to handle common synchronization, the mechanisms might be less explicit or customizable than, for example, Espresso's Idling Resources. Managing this at scale will be key.

  6. Debugging Challenges: If a Journey fails, debugging might involve understanding the gap between your natural language input, the AI's interpretation, and the actual UI state. This can be a different experience than debugging explicit test code.

  7. Tooling and Ecosystem Maturity: The ecosystem around Journeys (e.g., advanced reporting, CI/CD integration details, sophisticated debugging aids) is still developing compared to the mature ecosystems of frameworks like Espresso.

Being aware of these limitations helps set realistic expectations and informs where Journeys can provide the most value today.


Your First Journey: A Practical Demo with PinterestStyleGridDemo project

Important Caveat: The following steps are based on how new testing tools are typically integrated into Android Studio and general best practices. You will need to explore your specific version of Android Studio (especially if it's a Canary or Beta build that includes Journeys) to find the exact UI elements.

We'll use our PinterestStyleGridDemo app to create a simple Journey.

Scenario:

  1. Launch the app

  2. Verify the home screen (the image grid) is displayed

  3. Tap on the first image in the grid

  4. Verify that the detail screen for that image appears

Step 1: Locating the Journeys Tool in Android Studio

This is the most crucial part and depends on your Android Studio version. Here's how you might find it:

A. Through the Project View (Most Common for New Test Files):

  1. In the Project tool window (usually on the left), select the module where you want to create the Journey. For this initial, app-wide Journey, the :app module is a sensible choice

  2. Right-click on the app module (or a specific source set like src or potentially a newly designated journeys folder if one exists)

  3. Look for a "New" sub-menu

  4. Within "New," search for an option like "Journey," "AI Test Case," "Natural Language Test," or something similar

B. Via the Main Menu:

  1. Check the "File > New..." menu, similar to the above

  2. Explore the "Tools" menu. Sometimes, new experimental features or tools are housed there

  3. Look for a "Tools > AI Assistant" (or similar) sub-menu that might have an option for creating tests/Journeys

C. Using "Search Everywhere":

  1. Double-press the Shift key to open the "Search Everywhere" dialog

  2. Type "Journey," "Create Journey," "AI Test," or related keywords

D. Dedicated Tool Window:

  1. There might be a new Tool Window specifically for "Journeys" or "AI Testing." Look under "View > Tool Windows"

Action for you: Explore these locations in your Android Studio. The feature might be flagged as "Experimental."

Step 2: Creating the Journey File & Initial Setup

Once you've found the "Create Journey" action:

  1. Naming the Journey: A dialog will likely appear asking for a name. Choose a descriptive name

    • Example: HomeToDetailNavigationJourney or NavigateToImageDetailJourney or HomeToDetailFlow
  2. Choosing the Location (Path):

    • If prompted for a directory:

      • Default Suggestion: The IDE might suggest a default location

      • Best Practice Starting Point: For an app-level Journey like this one (launching the app and navigating), placing it within the :app module makes sense

      • Potential Locations within :app:

        • app/src/journeys (A new, dedicated directory for Journey files)

        • app/src/androidTest/journeys (If Journeys are treated similarly to instrumentation tests)

        • app/src/test/journeys (Less likely if they require a device/emulator)

  1. The Journey Editor/Interface: You should now see an editor or interface where you can input your natural language instructions

💡 Module Selection:

  • For this specific Journey that starts with app launch and involves navigation orchestrated by the :app module to show screens from :feature-home and :feature-detail, the :app module is the most appropriate owning module

  • Reasoning:

    • App Launch: The Journey starts with "Launch the app," which is inherently tied to the :app module's manifest and activity

    • Cross-Module Navigation: The flow transitions from :feature-home to :feature-detail. The :app module is typically responsible for the navigation graph that connects different feature modules

    • Overall User Experience: This is a test of a top-level user experience that a user would have with the complete application

  • When would you put Journeys in a feature module? (Teaser for Part 2):

    • If a Journey only tests functionality within a single feature module and doesn't navigate out

    • Example: A Journey in :feature-home that tests various sorting or filtering options on the home screen grid, but never leaves the home screen

    • This promotes better test modularity and allows feature teams to own tests specific to their features

Step 3: Writing the Natural Language Instructions

This is where you'll type the scenario you outlined:

Launch the PinterestStyleGridDemo app.
After the app loads, check that a grid of images is visible on the home screen.
Then, tap on the very first image in the grid.
Finally, verify that a new screen appears showing the details of the image.
  • Be Specific: Use names of screens or key UI elements if you know them

  • Iterative Process: Your first phrasing might not be perfect. That's okay!

Step 4: AI Interpretation & Preview (Conceptual)

The Journeys tool, powered by Gemini, will process your input

  • Look for Feedback: The IDE might show you the steps it has interpreted

  • Refine if Necessary: If the interpretation seems off, rephrase your natural language

Step 5: Running the Journey

  • Find the "Run" Button: There will be a way to execute the Journey

  • Select a Device/Emulator: Ensure you have a suitable emulator running or a device connected

  • Observe: Watch the emulator/device. Android Studio should attempt to perform the actions

💡 Troubleshooting: If you try this with the PinterestStyleGridDemo project, you may hit a FAIL_ON_PROJECT_REPOS Gradle error in convention-plugins/build.gradle.kts

  • Reason:

    • In root project's settings.gradle.kts file, it has a very important line repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)

    • This FAIL_ON_PROJECT_REPOS tells Gradle: "For this entire project, the only place you're allowed to define where to download plugins or dependencies (like google() or mavenCentral()) is within a settings.gradle.kts file. If any module's build.gradle.kts file tries to declare its own repositories {…} block, you must fail the build." This is a best practice for consistency and control in large projects.

    • In convention-plugins/build.gradle.kts, we have repositories {…} which a direct violation of the FAIL_ON_PROEJCT_REPOS rule set by the main project

  • Solutions:

    • We need to add pluginManagement { repositories { ... } } and ensured dependencyResolutionManagement { repositories { ... } } was correctly configured in convention-plugins/settings.gradle.kts.
    pluginManagement {
        repositories {
            gradlePluginPortal() // For plugins like kotlin-dsl itself
            google()
            mavenCentral()
        }
    }

    rootProject.name = "pinterest-convention-plugins"

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
        repositories { // For dependencies of the convention plugins themselves (like AGP, Kotlin Gradle Plugin)
            google()
            mavenCentral()
        }
        versionCatalogs {
            create("libs") {
                from(files("../gradle/libs.versions.toml"))
            }
        }
    }
  • Remove the entire repositories {…} block from convention-plugins/build.gradle.kts
plugins {
    `kotlin-dsl`
}

// Access versions from the catalog for these dependencies
dependencies {
    implementation("com.android.tools.build:gradle:${libs.versions.agp.get()}") // if agp version is in the catalog
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlin.get()}") // if kotlin version is in the catalog
}

gradlePlugin {
    plugins {
        register("androidLibrary") {
            id = "pinterest.android-library-convention"
            implementationClass = "com.vsay.pintereststylegriddemo.AndroidLibraryConventionPlugin"
        }
        register("kotlinLibrary") {
            id = "pinterest.kotlin-library-convention"
            implementationClass = "com.vsay.pintereststylegriddemo.KotlinLibraryConventionPlugin"
        }
        // Register other plugins here
    }
}

Step 6: Reviewing the Results

  • Success/Failure: The Journeys tool will report whether the Journey passed or failed

  • Failure Details: If it fails, it should indicate which natural language instruction or derived action failed

  • Debugging: This is where you'll iterate

    • Is the app in the state you expected?

    • Is your natural language clear enough?

    • Are there animations or delays causing issues?

Best Practices Highlighted in this Demo:

  • Clarity in Natural Language: The description is specific (e.g., "grid of images," "first image," "screen with image details"). Vague language is more likely to confuse the AI

  • Focus on User-Observable Behavior: The Journey checks for what the user sees ("grid of images," "details of the image")

  • Implicit vs. Explicit Locators (A Peek into the Future):

    • For "tap on the very first image," the AI tries to identify this element. Initially, it might use positional logic or simple heuristics

    • Best Practice Teaser (for Part 2): While this might work for a simple demo, relying on positional locators ("first item") can lead to flaky tests if the UI changes. In more robust Journeys, you'd want to ensure your app uses stable selectors like testTag or contentDescription, and your natural language hints at these when possible. For this "101" demo, we're seeing how far the AI can get with basic instructions

  • Keep it Simple for the First Time: This Journey covers a fundamental, stable flow. Don't try to boil the ocean with your first Journey


Key Takeaways & Starting Safely with Journeys

Android Studio Journeys are an exciting addition to the Android testing toolkit.

Recap of Strengths:

  • Potential for rapid test creation for key user flows

  • Increased accessibility for defining tests using natural language

  • Strong focus on the end-user experience in natural language

  • They lower the barrier for testing critical paths in large apps.

  • They complement — not replace — your existing test strategy.

Recap of Weaknesses/Considerations:

  • It's new technology: Expect evolution and learning curves

  • AI nuances: Natural Language interpretation isn't magic; clarity is key

  • Best for high-level flows initially, less so for complex edge cases or deep UI logic validation that Espresso/Compose handle well

How to Start Safely and Smartly:

  1. Begin with Critical "Happy Paths": Identify 2-3 core, stable, positive user flows in your app. These are excellent candidates for your first Journeys.

  2. Experiment and Iterate: Write a Journey, run it, and see how the AI interprets it. If it fails or does something unexpected, refine your natural language. Treat it as a conversation with the AI.

  3. Focus on Stable Flows: Choose parts of your app that don't undergo constant UI redesigns, as this will lead to more stable Journeys.

  4. Version Control Your Journeys: Journey definitions (whether natural language files or some other format) are part of your test assets. Store them in version control (e.g., Git) just like your source code and traditional tests. Review changes to Journeys in pull requests.

  5. Stay Informed: Keep an eye on Android Studio release notes and official documentation. The capabilities and best practices for Journeys will evolve.

  6. Don't Aim for 100% Replacement (Yet): Journeys are a complementary tool. Continue using Espresso/Compose UI tests for scenarios requiring fine-grained control, complex validations, or interaction with elements not easily described in high-level natural language.

Try creating your first Journey today: pick one happy-path flow, describe it in natural language, and see how far Gemini gets you. Then share your experience in the comments — I’d love to compare notes.


Thanks for reading! I hope you found this article on Android Journey helpful.

If you enjoyed this, you'd love my other articles.

Subscribe to my free newsletter to get my latest tutorials and coding insights delivered directly to your inbox. No spam, ever. Unsubscribe at any time.

📚 Android Studio Journeys: From Demo to Enterprise-Scale Testing

Part 1 of 2

Guide to Android Studio Journeys: from writing your first test to scaling across modular apps, CI pipelines, and large teams — with governance, privacy, and hybrid testing best practices.

Up next

📚 Android Studio Journeys — From Demo to Enterprise-Scale Testing - Part 2

Advanced Authoring for Real-World Modular Apps