Local Deploy to Multiple Emulators and Simulators with Cake
If you are looking for an easy way to test Xamarin.Forms or MAUI Application in a couple of Android Emulators and iOS Simulators at the same time — use Cake Script to do all routine work 🙃 😉
Hi Folks!!! 🤪 Long story short here is a link to the full script at GitHub Gist.
And my story begins — a year ago I saw a lovely speech from Damian, and just thought that it's pretty interesting to make scripts not in, instead of Bash and PowerShell. And I do nothing after that 😱.
In October, I read a blog post about all that once again:
And that stands in my head that we can make some UI Tests or Deployments with Cake for Xamarin.Forms Applications. And at the end of November, I realised that I needed to deploy to test the application I worked on at two Android Emulators(one RTL) and two iOS Simulators(one RTL). And don't that from Rider takes a lot of time. I don't need to Debug that. I have already done it when testing on my primary iOS Simulator. I just need to ensure it looks nice on each platform and Device.
Yes, yes, we can make UI Tests for that, but the truth is — not each project has those tests and not each required.
So, I take a look if that possible to build, get all Emulators and Simulator, deploy and run my app. And damn yeah 🤩 🥳.
Required Setup for Script
I used that only at one project right now, and I’m not done it as a completely modular script, but try to make it as much as I can flexible and easy for modifications.
Just replace all const strings with your full Path and that’s all you need. I think provided comments explain all in the depth 😛.
Clean and Re-Build Projects
And again, code for build and clean .Net
projects are really simple and have good code readability.
Get All Available Android Devices
This part of the script can get all attached for Debug Android Devices(via USB or via WiFi) and all started Emulators and print that to output(terminal)
Get All iOS Simulators
And here is a little bit tricky, because this part of the script shows all simulators. No matter if they are started or not! And according to official documentation, we can identify Simulator status with Availability
and IsAvailable
properties in returned objects. But output in a terminal shows me that Availability
is deprecated and IsAvailable
is all time True
(even if it’s not started). But the output of this script task is still useful because it can show correct names of Simulators which we can put into iosSimulators
Argument(at top of our script).
Build And Run Android App
This part of the script is slightly more complex, but still, I think you can understand what’s going on there. Here are just couple of interesting moments I would like to mention.
By Default Script works with BuildAndRunAndroid
and BuildAndRuniOS
that’s why we making build inside it as well. Yes we can make it before with IsDependentOn
but I don’t want to make it in that way(I’m lazy and want to hold it in separate tasks)
if(!device.Serial.StartsWith("emulator")){AdbUninstall(packageName: "you.com.YourBestProject", settings: settings);}
I found that only on real Android Devices uninstalling before installing is required.
Build And Run iOS
In my script, I want just to build Xamarin.Forms app in Debug|iPhoneSimulators
mode, which is not a common case 🤨. After not a long research I found that we can do this with XBuildSettings
:
But that doesn’t want work for me because I can’t find an output iOS app to deploy into Simulators 😥. After some experimentation, I realise that we can use standard MSBuild
to build and get that iOS app in output 🤗
A couple of words about this task in a script:
- I can’t identify if simulators are started or not.
- When I try to start the simulator from the script it does not react and doesn’t start. We need to start all required by ourselves before starting a script.
- The script waits till the Android app is installed, but don’t wait for the iOS app to be installed. That’s why we are waiting for 3s before launch.
End of Script
At the end of the script, we add a Default
Task and run requested Target
, where out target is an argument at top of the script and predefined to Default
Task.
Thanks for reading this. Once again a whole script at GitHub Gist