{"id":9458,"date":"2022-09-05T18:51:04","date_gmt":"2022-09-05T18:51:04","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=9458"},"modified":"2022-09-05T18:51:04","modified_gmt":"2022-09-05T18:51:04","slug":"appium-android-and-maui","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/appium-android-and-maui\/","title":{"rendered":"Appium, Android and MAUI"},"content":{"rendered":"<p><strong>Prerequisites<\/strong><\/p>\n<p>You&#8217;ll need Appium server (I&#8217;m using <a href=\"https:\/\/github.com\/appium\/appium-desktop\/releases\" rel=\"noopener\" target=\"_blank\">Appium Server UI<\/a>), I installed into my Windows c:\\tools\\Appium folder and next (whilst not a requirement but is very useful) grab the latest version of <a href=\"https:\/\/github.com\/appium\/appium-inspector\/releases\" rel=\"noopener\" target=\"_blank\">Appium Inspector<\/a> this will allows us to inspect elements within our running Android application, I unzipped this to c:\\tools\\AppiumInspector. <\/p>\n<p><em>Appium Server GUI has a button to run the inspector but, unless I&#8217;m missing something, this simply sends you to the GitHub repo for the inspector, so run the inspector yourself separately.<\/em><\/p>\n<p><strong>Creating a simple app.<\/strong><\/p>\n<p>Create yourself a MAUI application (mine&#8217;s call MauiUIAutomationTest, so you&#8217;re see this listed in various places below, if you create your own name, remember to update in the code as well). <\/p>\n<p>Like my previous Appium test samples the code is simple (I&#8217;ll recreate here). The MainPage.xaml within the ContentPage looks like this<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;Grid&gt;\r\n   &lt;Grid.RowDefinitions&gt;\r\n      &lt;RowDefinition \/&gt;\r\n      &lt;RowDefinition \/&gt;\r\n      &lt;RowDefinition \/&gt;\r\n   &lt;\/Grid.RowDefinitions&gt;\r\n\r\n   &lt;Entry Grid.Row=&quot;0&quot; AutomationId=&quot;input&quot; Margin=&quot;10&quot; Text=&quot;{Binding Input}&quot; \/&gt;\r\n   &lt;Button Grid.Row=&quot;1&quot; AutomationId=&quot;copy&quot; Margin=&quot;10&quot; Command=&quot;{Binding ProcessCommand}&quot; Text=&quot;Copy&quot; \/&gt;\r\n   &lt;Label Grid.Row=&quot;2&quot; AutomationId=&quot;output&quot; Margin=&quot;10&quot; Text=&quot;{Binding Output}&quot;\/&gt;\r\n&lt;\/Grid&gt;\r\n<\/pre>\n<p>I&#8217;m using MVVM Community Toolkit and so MainPageViewModel.cs is simply this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic partial class MainPageViewModel : ObservableObject\r\n{\r\n    &#x5B;ObservableProperty] private string input;\r\n    &#x5B;ObservableProperty] private string output;\r\n\r\n    &#x5B;RelayCommand]\r\n    private void Process()\r\n    {\r\n       Output = Input;\r\n    }\r\n}\r\n<\/pre>\n<p><strong>Creating our test code<\/strong><\/p>\n<p>I&#8217;ve created an NUnit test class library and added the NuGet package Appium.WebDriver (yes I know it&#8217;s an app. but that&#8217;s the NuGet package we need). If you&#8217;re creating your unit test class library from scratch you&#8217;ll need NUnit and NUnit3TestAdapter installed as dependencies as well).<\/p>\n<p>Now my first unit test is, as follows<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class Tests\r\n{\r\n    private AndroidDriver&lt;AndroidElement&gt; _driver;\r\n\r\n    &#x5B;SetUp]\r\n    public void Setup()\r\n    {\r\n        var driverOptions = new AppiumOptions();\r\n        driverOptions.AddAdditionalCapability(MobileCapabilityType.PlatformName, &quot;Android&quot;);\r\n        driverOptions.AddAdditionalCapability(MobileCapabilityType.AutomationName, &quot;UiAutomator2&quot;); \r\n        driverOptions.AddAdditionalCapability(MobileCapabilityType.DeviceName, &quot;Pixel_3_XL_API_29&quot;);\r\n\r\n        _driver = new AndroidDriver&lt;AndroidElement&gt;(new Uri(&quot;http:\/\/localhost:4723\/wd\/hub&quot;), driverOptions); \r\n        _driver.ActivateApp(&quot;com.companyname.mauiuiautomationtest&quot;);\r\n    }\r\n\r\n    &#x5B;TearDown]\r\n    public void TearDown()\r\n    {\r\n        _driver.Quit();\r\n    }\r\n\r\n    &#x5B;Test]\r\n    public void ChangeInput_ThenCopy_ExpectMatchingOutput()\r\n    {\r\n        var entry = _driver.FindElementById(&quot;com.companyname.mauiuiautomationtest:id\/input666&quot;);\r\n        entry.Clear();\r\n        entry.SendKeys(&quot;Hello World&quot;);\r\n        var button = _driver.FindElementById(&quot;com.companyname.mauiuiautomationtest:id\/copy666&quot;);\r\n        button.Click();\r\n        var label = _driver.FindElementById(&quot;com.companyname.mauiuiautomationtest:id\/output666&quot;);\r\n        Assert.That(label.Text, Is.EqualTo(&quot;Hello World&quot;));\r\n    }\r\n}\r\n<\/pre>\n<p>Obviously this is not perfect as we&#8217;re running the setup and tear down code after every test, but as I only have one test, I don&#8217;t care (it&#8217;s for the reader to do this correctly). Now we setup the driver options, the platformName is ofcourse Android, the deviceName relates to the device you&#8217;re using, I&#8217;m using the Android emulator for the Pixel 3 API 29, finally automationName specifies the automation engine to use, to be honest you could remove this and it&#8217;ll default the standard Appium engine but <a href=\"https:\/\/appium.io\/docs\/en\/drivers\/android-uiautomator2\/\" rel=\"noopener\" target=\"_blank\">UiAutomator2<\/a> is listed as Appiums flagship engine, so let&#8217;s use that.<\/p>\n<p>I had all sorts of issues trying to get Appium to start my MAUI app (as it will try to install it), however I think this is likely down to the way Visual Studio builds the apk, i.e. I probably need to publish a signed apk or the likes, but for now I&#8217;ll let Visual Studio deploy the app and then access it via Appium. Hence we have the following code to active an already installed app.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \r\n_driver.ActivateApp(&quot;com.companyname.mauiuiautomationtest&quot;);\r\n<\/pre>\n<p><strong>Eager to see something working?<\/strong><\/p>\n<p>If you&#8217;re eager to see something working, then <\/p>\n<ul>\n<li>Deploy your application to your Android emulator (I just get Visual Studio to deploy it)<\/li>\n<li>Run the Appium Server GUI and start a new session<\/li>\n<li>Run your unit test<\/li>\n<\/ul>\n<p>If all went well the test was green and if not, check your application name etc. <\/p>\n<p><strong>Appium Inspector<\/strong><\/p>\n<p>The Appium server does not come with an inspector now, you need to download it separately (as stated earlier). Ofcourse we can probably get a lot done without an inspector, but it helps and gives confidence that if it see&#8217;s our id&#8217;s etc. then Appium will. You&#8217;ll need to tell the inspector to connect to the Appium server &#8211; make sure that Remote Path has the URL <em>\/wd\/hub<\/em> and you have valid the following Desired Capabilities<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;appium:automationName&quot;: &quot;UIAutomator2&quot;,\r\n  &quot;appium:deviceName&quot;: &quot;Pixel_3_XL_API_29&quot;,\r\n  &quot;platformName&quot;: &quot;Android&quot;\r\n}\r\n<\/pre>\n<p>Ensure your have Appium server is running. Before you run the inspector just make sure your app. is running (just makes things simpler) and now start a session from your Appium Inspector. It should show you the screen of the current running application.<\/p>\n<p>As you can see from the code below, we expect a &#8220;copy&#8221; automation id<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n&lt;Button Grid.Row=&quot;1&quot; AutomationId=&quot;copy&quot; Margin=&quot;10&quot; Command=&quot;{Binding ProcessCommand}&quot; Text=&quot;Copy&quot; \/&gt;\r\n<\/pre>\n<p>MAUI AutomationId&#8217;s do not appear as AutomationId or Accessibility Id for that matter, but instead they become id&#8217;s but prefixed with you app name, i.e. that&#8217;s why our unit tests has <em>com.companyname.mauiuiautomationtest:id\/output<\/em>. All that really matters is that we have a unique value on an Appium accessible property to do some UI Automation testing. We do have the option of XPath locators, but these should probably be used as a the last resort, if we do not have anything else to locate against. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Prerequisites You&#8217;ll need Appium server (I&#8217;m using Appium Server UI), I installed into my Windows c:\\tools\\Appium folder and next (whilst not a requirement but is very useful) grab the latest version of Appium Inspector this will allows us to inspect elements within our running Android application, I unzipped this to c:\\tools\\AppiumInspector. Appium Server GUI has [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[120,334,330],"tags":[],"class_list":["post-9458","post","type-post","status-publish","format-standard","hentry","category-android","category-appium","category-maui"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9458","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=9458"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9458\/revisions"}],"predecessor-version":[{"id":9472,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/9458\/revisions\/9472"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=9458"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=9458"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=9458"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}