Speed Up Your Tests: Unlocking XCUI Automation Parallel Execution

automation May 9, 2025

At Halodoc, we're constantly searching for ways to optimize our testing processes. As our iOS application grows in complexity, so does the need for comprehensive UI testing. However, with this growth comes a challenge: maintaining fast test execution times to support our rapid development cycles. Parallel testing is one of the most powerful tools we've implemented to address this challenge, allowing us to dramatically decrease testing time without sacrificing coverage.

In this blog post, we'll explore how we've unlocked parallel execution for our UI automation tests and the significant impact it's had on our development workflow.

The Challenge of Growing Test Suites

As modern mobile applications become more complex, test suites inevitably grow larger. A typical iOS app might have hundreds of UI test scenarios covering various features, user flows, and edge cases. Running these tests sequentially can take hours, creating a bottleneck in the development process and slowing down release cycles.

For our team at Halodoc, this challenge became particularly acute as we expanded our healthcare services across Indonesia. With each new feature added to our teleconsultation, medicine delivery, lab services, and innovative digital clinics, our test suite expanded accordingly. Waiting hours for test feedback became unsustainable.

Understanding Parallel UI Testing in Xcode

Parallel Testing in Xcode

Xcode provides built-in support for parallel test execution, but understanding how it works is crucial to leveraging it effectively. Parallel testing operates at a higher level by distributing test classes or feature files across multiple simulator instances.

How Parallel UI Testing Works:

  1. Multiple Simulator Instances: When parallel testing is enabled, Xcode creates multiple simulator clone instances to execute tests concurrently. By default, Xcode launches five simulator clones, distributing test classes or feature files across these dedicated simulator clone instances.
  2. Test Class Distribution: Each test class or feature file (if using Cucumberish) is treated as a separate entity that can run independently on each clone simulator instance.
  3. Independent Execution Environments: Each simulator is a clone with its own isolated environment - changes to one simulator (such as user login, cached data, or file system modifications) don't affect others. This isolation is crucial for preventing test interference when running in parallel.
  4. Resource Optimization: Xcode automatically manages the distribution of test classes or feature files based on available simulator clone resources.
  5. Results Aggregation – Once all tests are completed, results are collected and merged into a final report.

Parallel Testing with Existing XCUI and Cucumberish Framework

Our UI automation at Halodoc utilizes native XCUITest and Cucumberish for BDD-style tests. We embrace Behavior-Driven Development (BDD) with Cucumberish because it bridges the communication gap between technical and non-technical stakeholders. The human-readable gherkin syntax allows product managers, QA specialists, and developers to collaborate on test scenarios using a common language. This approach ensures our tests not only verify functionality but also document expected behavior from the user's perspective.

Implementation Guide:

1. Delete Simulator Environment Before Configuration

When implementing parallel test execution, we encountered a major obstacle. We were not able to achieve parallel test execution and struggled considerably until we identified a critical prerequisite. Before setting up parallel execution, we needed to remove all existing simulators to avoid conflicts during test runs. This was a crucial one-time setup step. This cleanup process prevents device allocation conflicts, which were causing intermittent failures and unpredictable behavior in our parallel execution attempts.

xcrun simctl delete all

2. Organize Test Scenarios Strategically

The key to effective parallel testing is distributing your tests across multiple files. In our Cucumberish setup, this meant organizing scenarios into separate feature files based on feature areas:

Organised User Flows into Multiple Feature Files

If you're using native XCUITest without Cucumberish, you can achieve the same parallelization by creating multiple test classes:

Using Multiple Test Classes

Each feature file or XCTestCase class becomes a separate test class in Xcode, allowing them to run in parallel on different clone simulator instances.

3. Enable Parallel Execution

In your UI test target settings within Xcode, enable the Execute in Parallel option:

  1. Select your project in the Project Navigator
  2. Select the UI Test target
  3. Click on Edit Scheme
  4. Select the Test action
  5. Click on Options... at the bottom
  6. Check Execute in parallel
Enabling Parallel Execution for UI Testing Target

For CI/CD pipelines or command-line builds, you can enable parallel testing through xcodebuild with the -parallel-testing-enabled flag:

xcodebuild -project YourProjectName.xcodeproj
-scheme 'SchemeName'
-sdk iphonesimulator
-destination 'platform=iOS Simulator,OS=18.4,name=iPhone 16'
test-without-building
-testPlan ParallelTestPlan
-parallel-testing-enabled YES

4. Structure Tests for Independence

For parallel UI testing to work reliably, test isolation is critical. Each test class must function independently, as if it's the only one running, regardless of how or when it executes. Here's how to ensure that:

Shared state between test classes or even between test methods is one of the most common causes of flaky, non-deterministic test results in parallel execution. Shared state can take many forms:

  • Global variables or static properties
  • Singleton instances reused across tests
  • Shared files or database records
  • Test data in a remote environment (e.g., backend APIs) that's reused or modified by multiple tests

For example, imagine two test classes:

  • One creates a mock user and tries to do a transaction
  • Another test tries to delete that same user

Suppose both tests run in parallel and use the same user. In that case, their outcomes become unpredictable — one might delete the user while the other is still trying to complete a transaction, causing a failure. To ensure reliable parallel execution, each test must operate in complete isolation. Eliminating shared state is the foundation for stable, deterministic, and scalable UI testing.

5. Balance Test Distribution

Effective parallelization is not just about enabling simultaneous execution — it's also about how you distribute tests across feature files or test classes. Uneven distribution can create performance bottlenecks where one long-running test file delays the completion of the entire test suite, limiting the impact of parallel execution.

In Xcode, test distribution for parallel execution happens at the test class or feature file level. If one test class significantly outweighs the others in runtime, simulators executing shorter tests will complete early and remain idle, while the longest-running test holds up the overall suite. This leads to underutilized resources and diminished parallelization benefits.

Consider the following example test run:

Before Balanced Test Distribution

When run in parallel, the clone simulators executing the shortest time-consuming test files (Login.feature: 7 min, MedicineDelivery.feature: 6 min, Appointment.feature: 5 min) will finish quickly, while the simulator handling FullRegression.feature (15 min) continues running, effectively becoming a single point of delay. The entire test suite's execution time ends up constrained by the slowest test file, negating much of the potential benefit from parallelization.

After Balanced Test Distribution

To mitigate this bottleneck effect, we recommend refactoring large test files into smaller, more balanced units with comparable runtimes. In the example above, FullRegression.feature, it could be decomposed into three separate feature files (ContactDoctor.feature, ScheduleDoctor.feature, LabBooking.feature), each requiring approximately 5 min of execution time. This strategic restructuring enables simulators to process tests with similar execution durations, ensuring optimal load distribution across available resources and maximizing concurrency efficiency. The result is a reduction in total execution time from 15 min to 7 min, a remarkable 53% improvement in overall test suite performance.

Results: Real-world Performance Gains

After implementing parallel UI testing, we experienced transformative improvements in test execution time and overall efficiency.

One of the most compelling outcomes came from a particularly large and complex UI testing target:
Execution time dropped from ~2 hour to just ~40 min — a remarkable ~66.7% reduction.

This improvement wasn't an isolated case. Across the board, our test suites now run significantly faster, empowering us to:

  • Accelerate CI/CD pipelines
  • Shorten feedback loops for developers
  • Increase test frequency without resource bottlenecks
  • Catch regressions earlier, with higher confidence

Parallel testing has shifted UI automation from a bottleneck into a strategic advantage, enabling rapid, reliable releases without compromising on quality.

Conclusion

Parallel UI testing has greatly improved our development workflow at Halodoc. By cutting down test execution time by ~67%, we removed a major delay in our release process without losing test coverage or quality. This wasn’t just about turning on a feature in Xcode—it required careful planning, making sure tests don’t depend on each other, and spreading test scenarios smartly across files.

The key practices we followed—test independence, even distribution, and proper environment setup—can be used in any mobile testing framework, not just for iOS.

As Halodoc continues to grow across Indonesia, faster test feedback helps us release new features and updates more quickly. This means our millions of users get a better, more reliable healthcare experience every day.

References

Here are some useful references related to parallel testing in Xcode

  1. Testing Tips & Tricks
  2. Get your test results faster
  3. The order of random and parallel Unit Tests in Xcode

These references will help in understanding best practices and improving test reliability while running tests in parallel.

Join us

Scalability, reliability, and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels, and if solving hard problems with challenging requirements is your forte, please reach out to us with your resume at careers.india@halodoc.com.

About Halodoc

Halodoc is the number one all-around healthcare application in Indonesia. Our mission is to simplify and deliver quality healthcare across Indonesia, from Sabang to Merauke.
Since 2016, Halodoc has been improving health literacy in Indonesia by providing user-friendly healthcare communication, education, and information (KIE). In parallel, our ecosystem has expanded to offer a range of services that facilitate convenient access to healthcare, starting with Homecare by Halodoc as a preventive care feature that allows users to conduct health tests privately and securely from the comfort of their homes; My Insurance, which allows users to access the benefits of cashless outpatient services in a more seamless way; Chat with Doctor, which allows users to consult with over 20,000 licensed physicians via chat, video or voice call; and Health Store features that allow users to purchase medicines, supplements and various health products from our network of over 4,900 trusted partner pharmacies. To deliver holistic health solutions in a fully digital way, Halodoc offers Digital Clinic services including Haloskin, a trusted dermatology care platform guided by experienced dermatologists.
We are proud to be trusted by global and regional investors, including the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek, and many more. With over USD 100 million raised to date, including our recent Series D, our team is committed to building the best personalized healthcare solutions — and we remain steadfast in our journey to simplify healthcare for all Indonesians.

Tags

Syed Mansoor

Software Engineer @ Halodoc