DEV Community

Om Narayan
Om Narayan

Posted on • Originally published at devicelab.hashnode.dev

Went in to support Maestro for physical devices. Came out with even more.

The Backstory

iOS real device support has been one of Maestro's most requested features since January 2023.

Almost three years of developers asking for the same thing. Issue after issue. Comment after comment.

We looked at the codebase. Surprisingly, a lot of groundwork was already there. Infrastructure PRs had been merged. The foundation existed.

It just needed someone to finish the last mile.


Why Us?

At DeviceLab, we run tests on real devices every day. It's literally what we do.

When our customers started asking for Maestro support on physical iOS devices, we had the context—and the motivation—to build it.

So we did.

We submitted PR #2856 to give it back to the community.

But here's the thing: The Maestro team has indicated official iOS real device support won't land until next year. No committed timeline. Our PR won't help anyone until it's merged—or until they build their own solution.

We didn't want teams to wait that long.

That's why we packaged a ready-to-use tool.


What It Looks Like

Your existing Maestro flows. Real iPhones. No changes.

appId: com.example.app
---
- launchApp
- tapOn: "Login"
- inputText: "user@example.com"
- tapOn: "Submit"
- assertVisible: "Welcome"
Enter fullscreen mode Exit fullscreen mode

Same YAML. Same commands. Just real devices.

Tested on: iOS 26.x and iOS 18.x, including parallel execution on multiple devices.


Under the Hood

Getting Maestro to talk to real iOS devices required four pieces:

1. Device Detection

Maestro's iOS driver was built for simulators. We taught it to recognize physical devices with Developer Mode enabled.

2. XCTest Runner

The XCTest driver needed to be built and deployed to actual hardware—not just the simulator. This requires code signing with a valid Apple Developer certificate.

3. Port Forwarding

Simulators run on localhost. Real devices don't.

We bridge that gap:

localhost:6001 → device:22087
Enter fullscreen mode Exit fullscreen mode

4. Session Management

Real devices have constraints simulators don't. We handle them gracefully—like clearState working via app reinstall instead of simctl commands.


The Architecture

┌─────────────┐     ┌──────────────────┐     ┌─────────────┐
│   Maestro   │────▶│ maestro-ios-device│────▶│ iOS Device  │
│  (patched)  │     │  (port forward)  │     │ (XCTest)    │
└─────────────┘     └──────────────────┘     └─────────────┘
     :6001                                        :22087
Enter fullscreen mode Exit fullscreen mode
  • maestro-ios-device builds and installs the XCTest runner on your device
  • The runner starts an HTTP server on the device
  • Port forwarding connects your local Maestro to the device
  • Your tests run exactly as they would on a simulator

Bonus: Parallel Testing

While we were in there, we unlocked something else.

Running tests on multiple devices simultaneously? Wasn't possible before. Hardcoded port limitation.

Now it is:

# Terminal 1
maestro-ios-device --team-id ABC123 --device DEVICE_1 --driver-host-port 6001

# Terminal 2
maestro-ios-device --team-id ABC123 --device DEVICE_2 --driver-host-port 6002
Enter fullscreen mode Exit fullscreen mode

Parallel testing on real iOS devices. Finally.


The Honest Limitations

We're not claiming this is perfect. Some iOS platform restrictions apply:

Command Status Notes
clearState ✅ Works Via app reinstall (requires --app-file)
setLocation ⚠️ Limited Requires additional setup
addMedia ❌ Not supported iOS restriction

These are Apple's limitations, not ours.


Try It

Install:

curl -fsSL https://raw.githubusercontent.com/devicelab-dev/maestro-ios-device/main/setup.sh | bash
Enter fullscreen mode Exit fullscreen mode

Start the device bridge:

maestro-ios-device --team-id YOUR_TEAM_ID --device DEVICE_UDID
Enter fullscreen mode Exit fullscreen mode

Run your tests (in another terminal):

maestro --driver-host-port 6001 --device DEVICE_UDID --app-file /path/to/app.ipa test flow.yaml
Enter fullscreen mode Exit fullscreen mode

Full docs: github.com/devicelab-dev/maestro-ios-device


Compatibility

Maestro Version Status
2.0.10 ✅ Supported
2.0.9 ✅ Supported
Other versions ❌ Not tested

⚠️ Disclaimer

This is an unofficial community tool. Not supported by mobile.dev or the Maestro team. Use at your own risk.

When Maestro releases official iOS device support, we recommend switching to the official version.


Links


Built by DeviceLab—stop renting devices you already own.

Top comments (0)