Monday, 23 December 2019

Dynamics 365 UI Automation using EasyRepro





Hello Everyone,

Today I am going to write an article for the beginners who have just started exploring options to automate Dynamics 365 testing (UI and Functional both).

Those who are not aware about the EasyRepro in Dynamics 365. Here we go...

EasyRepro is a library or framework which is build on top of Selenium, provides dynamics folks ability to facilitate automate UI testing specifically on the Dynamics 365 projects. This framework provides an easy to use set of commands/test cases that make setting up UI testing quick and easy. 

Let's take a very simple use case to understand how EasyRepro works.

Use Case: Create a contact in Dynamics 365 Unified Client Interface.

In order to create Contact in Dynamics 365 UCI, one needs to perform following steps manually, .
  1. Open Dynamics 365 Instance
  2. Enter Credentials
  3. Handle Single Sign On (SSO) and Additional Popups.
  4. Login to Dynamics 365 CE Unified Client Interface
  5. Open 'Sales Hub' App
  6. Navigate to Sales > Contacts > Active Contacts
  7. Click 'New' to create a new Contact record
  8. Auto fill Information
  9. Save the Record.
  10. Capture the screenshot and recording of complete testing
However using EasyRepro framework, we'll perform these steps automatic without any human intervention...

So Lets get started...

Create a Unit Test project:




























Add the required NuGet packages:

Dynamics365.UIAutomation.API








Selenium.Chrome.WebDriver











System.Configuration.ConfigurationManager











Once installation of all the required Nuget Packages is done. Your package.config file will look like below:















Add a Basic UI Test Case:

























Paste the following Code:

using System;
using System.Net;
using System.Security;
using Microsoft.Dynamics365.UIAutomation.Api.UCI;
using Microsoft.Dynamics365.UIAutomation.Browser;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;

namespace D365CEUIAutomation
{
    [TestClass]
    public class CreateContact
    {
        private readonly SecureString _username = System.Configuration.ConfigurationManager.AppSettings["CRMUser"].ToSecureString();
        private readonly SecureString _password = System.Configuration.ConfigurationManager.AppSettings["CRMPassword"].ToSecureString();
        private readonly Uri _xrmUri = new Uri(System.Configuration.ConfigurationManager.AppSettings["CRMUrl"].ToString());

        private static BrowserOptions _options = new BrowserOptions
        {
            BrowserType = BrowserType.Chrome,
            PrivateMode = true,
            FireEvents = false,
            Headless = false,
            UserAgent = false,
        };

        [TestMethod, TestCategory("BuildAutomation")]
        public void TestMethod1()
        {
            var client = new Microsoft.Dynamics365.UIAutomation.Api.UCI.WebClient(_options);

            using (var xrmApp = new XrmApp(client))
            {
                xrmApp.ThinkTime(5000);

                var url = System.Configuration.ConfigurationManager.AppSettings["CRMUrl"].ToString();
                var user = System.Configuration.ConfigurationManager.AppSettings["CRMUser"].ToString();
                var pwd = System.Configuration.ConfigurationManager.AppSettings["CRMPassword"].ToString();

                Console.WriteLine("Read the Configuration Data");

                client.Browser.Driver.Navigate().GoToUrl(_xrmUri);

                xrmApp.ThinkTime(5000);

                Console.WriteLine("Application Redirection Successfull");

                // Check whether browser is asking to enter Username
                if (client.Browser.Driver.HasElement(By.Id("i0116")))
                {
                    client.Browser.Driver.FindElement(By.Id("i0116")).SendKeys(user);

                    xrmApp.ThinkTime(2000);

                    Console.WriteLine("Entered Username");

                    client.Browser.Driver.FindElement(By.Id("i0116")).SendKeys(Keys.Enter);

                    Console.WriteLine("Press Enter");
                }
                else
                {
                    Console.WriteLine("No Username Control Found - SSO");
                }

                // Check whether browser is asking to enter Password
                if (client.Browser.Driver.HasElement(By.Id("i0118")))
                {
                    client.Browser.Driver.FindElement(By.Id("i0118")).SendKeys(pwd);

                    xrmApp.ThinkTime(2000);

                    Console.WriteLine("Entered Password");

                    client.Browser.Driver.FindElement(By.Id("i0118")).SendKeys(Keys.Enter);

                    Console.WriteLine("Press Enter");
                }
                else
                {
                    Console.WriteLine("No Password Control Found - SSO");
                }


                // Check whether browser is asking for confirmation 'Keep Signing In'
                if (client.Browser.Driver.HasElement(By.Id("idSIButton9")))
                {
                    client.Browser.Driver.FindElement(By.Id("idSIButton9")).SendKeys(Keys.Enter);
                }
                else
                {
                    Console.WriteLine("No 'Stay Signed In' Dialog appeared");
                }

                xrmApp.ThinkTime(5000);

                xrmApp.Navigation.OpenApp("Sales Hub");

                Console.WriteLine("Navigation to App successfull");

                xrmApp.ThinkTime(2000);

                xrmApp.Navigation.OpenSubArea("Sales", "Contacts");

                Console.WriteLine("Navigation to SubArea successfull");

                xrmApp.ThinkTime(2000);

                xrmApp.CommandBar.ClickCommand("New");

                Console.WriteLine("Clicked on New to create Record");

                xrmApp.ThinkTime(5000);

                Console.WriteLine("Set Value in CRM UCI Form successfull");

                xrmApp.ThinkTime(2000);

                xrmApp.Entity.Save();

                Console.WriteLine("Records has been Saved successfully");

                Screenshot ss = ((ITakesScreenshot)client.Browser.Driver).GetScreenshot();
                ss.SaveAsFile(@"..\TestResultEvidence\SeleniumTestingScreenshot"+ ".jpg");
                Console.WriteLine("Capture Screenshot as Test Result Evidence");

            }

        }
    }
}

Let's Understand the code:

Here is the code to retrieve the CRM Instance details like URL, Username and Password from app.config file.'

var url = System.Configuration.ConfigurationManager.AppSettings["CRMUrl"].ToString();
                var user = System.Configuration.ConfigurationManager.AppSettings["CRMUser"].ToString();
                var pwd = System.Configuration.ConfigurationManager.AppSettings["CRMPassword"].ToString();


Here is the code to defined the Browser settings on which the UI Test case will run.

 private static BrowserOptions _options = new BrowserOptions
        {
            BrowserType = BrowserType.Chrome,
            PrivateMode = true,
            FireEvents = false,
            Headless = false,
            UserAgent = false,
        };

Note: Here 'Headless' property decides whether you want to execute/run the test case in background without opening the browser screen (set Headless to True) or want to watch the graphical user interface of the test case (set Headless to False)


This line use to open the Dynamics 365 URL

client.Browser.Driver.Navigate().GoToUrl(_xrmUri);

However, In some blogs/article even in the GITHUB following line is being used to open the Dynamics URL:

xrmApp.OnlineLogin.Login(_xrmUri, _username, _password);

However, It doesn't work in following scenarios.
  • If Single Sign On (SSO) is enabled in your organisation- In case of Single Sign On, you directly gets entered in CRM Instance without entering the credential and the above given line tries to find the control in browser screen in order to put username and password which doesn't exist and test case gets failed.
  • If Browser gives popup to Stay Signed in after entering the credentials. See below.  -  If SSO is not enabled, however after entering the credential if browser gives you popup to Stay Signed In? and your test case tries to find the Dynamics Screen after enter the credential which it doesn't exist unless we choose Yes or No in the below screen. Hence test case again gets failed.



You can check these issues are also posted by lot of folks in GITHUB:


Now the ques is, what is the solution to handle such issues?

Here is the answer !!

After opening the Dynamics 365 URL, Check whether Browser is asking to enter the Username or Username Control is present on the browser screen. Here is the code for that:

client.Browser.Driver.HasElement(By.Id("i0116"))

If return YES, that means SSO is not enabled in the Organisation and you just simply need to enter the Username. Here is the code for that, where (user) is the variable name which stores username

client.Browser.Driver.FindElement(By.Id("i0116")).SendKeys(user);

After entering the Username, you need to click Enter in order to proceed to the Next screen where you have to enter Password. Here is the code for that:

client.Browser.Driver.FindElement(By.Id("i0116")).SendKeys(Keys.Enter);

Use wait in between so that browser can find that control. Can increase/decrease based on your network connectivity and system performance.

Here is the complete code for finding the username control and then entering the username. 

               // Check whether browser is asking to enter Username

                if (client.Browser.Driver.HasElement(By.Id("i0116")))
                {
                    client.Browser.Driver.FindElement(By.Id("i0116")).SendKeys(user);

                    xrmApp.ThinkTime(2000);

                    Console.WriteLine("Entered Username");

                    client.Browser.Driver.FindElement(By.Id("i0116")).SendKeys(Keys.Enter);

                    Console.WriteLine("Press Enter");
                }
                else
                {
                    Console.WriteLine("No Username Control Found - SSO");
                }

Here is the code for finding the Password control and then entering the Password same as Username.

               // Check whether browser is asking to enter Password
                if (client.Browser.Driver.HasElement(By.Id("i0118")))
                {
                    client.Browser.Driver.FindElement(By.Id("i0118")).SendKeys(pwd);

                    xrmApp.ThinkTime(2000);

                    Console.WriteLine("Entered Password");

                    client.Browser.Driver.FindElement(By.Id("i0118")).SendKeys(Keys.Enter);

                    Console.WriteLine("Press Enter");
                }
                else
                {
                    Console.WriteLine("No Password Control Found - SSO");
                }


Here is the code to handle the Popup asking to Stay Signed In.

If Popup appears then hit Enter to Choose Yes and proceed to the Dynamics screen.

              // Check whether browser is asking for confirmation 'Keep Signing In'
                if (client.Browser.Driver.HasElement(By.Id("idSIButton9")))
                {
                    client.Browser.Driver.FindElement(By.Id("idSIButton9")).SendKeys(Keys.Enter);
                }
                else
                {
                    Console.WriteLine("No 'Stay Signed In' Dialog appeared");
                }


Here is the code to Open Sales Hub Model Driven App

xrmApp.Navigation.OpenApp("Sales Hub");

Here is the code to Click on Contacts under Sales subarea

xrmApp.Navigation.OpenSubArea("Sales", "Contacts");

Here is the code to Click on +New in order to create New Contact record

xrmApp.CommandBar.ClickCommand("New");

Here is the code to enter some sample values in firstname, lastname and emailaddress control in contact form.

 xrmApp.Entity.SetValue("firstname", "Arpit");
 xrmApp.Entity.SetValue("lastname", "Shrivastava");
 xrmApp.Entity.SetValue("emailaddress1", "arpit.crmconsultant@gmail.com");

Here is the code to Save the Contact record

xrmApp.Entity.Save();

Here is the code to Capture the screenshot in JPG format of final screen and store it in TestResultEvidence folder exists inside Bin folder of Main Project

Screenshot ss = ((ITakesScreenshot)client.Browser.Driver).GetScreenshot();
ss.SaveAsFile(@"..\TestResultEvidence\SeleniumTestingScreenshot"+ ".jpg");

Add App.Config to store Dynamics 365 Instance information:




































Add a Folder to store Testing Evidence:






Run the Test:






















Test Result and Screenshot of Evidence:



Capture Video of Complete UI Testing :

You’ll need to add a .runsettings file to your solution. To do so, right-click on your solution and add a new item (XML file) and make sure it’s named something like settings.runsettings, the .runsettings extension being key. Make sure this file gets into source control.

Paste below content in settings.runsettings file.to get recordings working:


<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
   <RunConfiguration>
     <ResultsDirectory>.\TestResults</ResultsDirectory>
   </RunConfiguration>
   <DataCollectionRunSettings>
     <DataCollectors>
       <DataCollector uri="datacollector://microsoft/VideoRecorder/1.0"
                      assemblyQualifiedName="Microsoft.VisualStudio.TestTools.DataCollection.VideoRecorder.VideoRecorderDataCollector, Microsoft.VisualStudio.TestTools.DataCollection.VideoRecorder, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                      friendlyName="Screen and Voice Recorder">
         <!--Video data collector was introduced in Visual Studio 2017 version 15.5 -->
       </DataCollector>
     </DataCollectors>
   </DataCollectionRunSettings>
</RunSettings>


In Visual Studio, under the Test menu –> Test Settings select Select Test Settings File and choose the new .runsettings file.

And it should be as simple as that. After a test executes in the test results folder there should be a sub-folder with a guid for a name and inside it will be a .wmv file which is the recording of the test being run in the browser. 



Hope it helps someone. I have seen lot of folks are struggling to find the alternative to get rid of all the issues they are facing while running the UI test cases directly downloaded from Github.

Please do share your feedback and get back to me in case of any query/issues.

Stay Tuned. Cheers.

6 comments:

  1. This is something that you just read and read. You just can’t get tired of it.Automation testing

    ReplyDelete
  2. Been searching for such a remarkable blog like this for a long time.
    alpinestars gloves

    ReplyDelete
  3. hello , I have custom model driven app in UCI , its not opening xrmApp.Navigation.OpenApp(UCIAppName.customApp);with this ..
    Can anyone please help

    ReplyDelete
  4. Hi can i get session on this framework for uci app and may i know what is the cost of this course as well

    ReplyDelete

Blogger Widgets