Thu, 01/28/2021 - 18:49 By Amaury Veron
3 comments
Dynamics 365 EasyRepro

Dynamics 365 EasyRepro : 

Introduction

How much time do you spend testing your Dynamics 365 features again and again for every new release ?

If the answer is... "too much", then this Chronicle is for you ;)

Let me introduce you... EasyRepro. This C# Framework uses the driver of your browser to execute a suite of actions in Dynamics 365 through the User Interface, mirroring real user actions. The goal being to test that your CRM works as you expect.

This Chronicle will present the Framework. With a quick tutorial, it will show you how to set it up and start using it. Then, to go a bit further, it will expose a sample script that I wrote to test the Lead-Opportunity process: from creating a Lead, Qualifying it, to Closing the associated Opportunity. And it will finally show the range of functionalities covered.

 

Selenium Quick Presentation

Dynamics 365 EasyRepro is based on Selenium (a famous framework that you might already have heard of).

Selenium is a framework for testing web applications. It uses the web driver of your browser to emulate the interaction of the user with it. It is compatible with most web browsers.

When writing a script you could for instance ask Selenium to:

  • Open the URL of your web page. With a request of that kind:

webDriver.Navigate().GoToUrl("https://www.example.com");

  • Ask Selenium to click on a button. With a request of that kind:

webDriver.findElement(By.id("submit")).click();

Note that here the button is found through his id in the DOM.

  • Then, you would like to get the h1 title in your page. With a request of that kind:

String myh1Title = webDriver.findElement(By.cssSelector("h1")).getText();

  • And finally you would check that your title has the expected text:

assertEquals(myh1Title , "That's my h1 title in this page");

If you want to dig into this, you can find the complete documentation of Selenium here: https://www.selenium.dev/documentation/en/

 

EasyRepro Presentation

So, Dynamics 365 EasyRepro is based on Selenium. Selenium uses a language "technical", in the sense that it makes you manipulate the source code of your web page.

With EasyRepro, nothing like that. You will only write commands that have a "Dynamics 365 meaning". Like:

  • OpenRecord()
  • BusinessProcessFlow.SetActive()
  • ClickCommand()
  • OpenEntity()
  • OpenAppsForDynamicsCRM()
  • ....

All these methods will execute (for you) Selenium scripts manipulating the source code of the D365 application.

Let's take an example. In a test we start from the View "All Cases" and we want to show the View "Active Cases".

Dynamics 365 EasyRepro

 As a user, we would Click on the list of the available Views:

Dynamics 365 EasyRepro

And we would select "Active Cases":

Dynamics 365 EasyRepro

 

  • To implement this test with Selenium we would need to understand the HTML code of Dynamics 365 to ask Selenium to:
    • Find the button to display the list of Views, using the DOM.
    • Click on this button.
    • Then find the DOM element "Active Cases"
    • And click on it
    • While making sure that the elements had time to load, managing exceptions and stuff like that

 

  • With Dynamics 365 EasyRepro , you would use this one-line command:
    • WebClient.SwitchView("Active Cases")

And this is all. No need to understand the D365 code, just speak to EasyRepro like you would speak to a user (I mean, almost).

Behind the scenes, this method executes the code below based on Selenium:

        internal BrowserCommandResult<bool> SwitchView(string viewName, string subViewName = null, int thinkTime = Constants.DefaultThinkTime)
        {
            ThinkTime(thinkTime);

            return Execute(GetOptions($"Switch View"), driver =>
            {
                var views = OpenViewPicker().Value;
                Thread.Sleep(500);
                var key = viewName.ToLowerString();
                bool success = views.TryGetValue(key, out var view);
                if (!success)
                    throw new InvalidOperationException($"No view with the name '{key}' exists.");

                view.Click(true);

                if (subViewName != null)
                {
                    // TBD
                }

                driver.WaitForTransaction();

                return true;
            });
        }

Which calls another EasyRepro method "OpenViewPicker":

        public BrowserCommandResult<Dictionary<string, IWebElement>> OpenViewPicker(int thinkTime = Constants.DefaultThinkTime)
        {
            ThinkTime(thinkTime);

            return Execute(GetOptions("Open View Picker"), driver =>
            {
                driver.ClickWhenAvailable(By.XPath(AppElements.Xpath[AppReference.Grid.ViewSelector]),
                    TimeSpan.FromSeconds(20),
                    "Unable to click the View Picker"
                );

                var viewContainer = driver.FindElement(By.XPath(AppElements.Xpath[AppReference.Grid.ViewContainer]));
                var viewItems = viewContainer.FindElements(By.TagName("li"));

                var result = new Dictionary<string, IWebElement>();
                foreach (var viewItem in viewItems)
                {
                    var role = viewItem.GetAttribute("role");
                    if (role != "option")
                        continue;

                    var key = viewItem.Text.ToLowerString();
                    if (string.IsNullOrWhiteSpace(key))
                        continue;

                    if (!result.ContainsKey(key))
                        result.Add(key, viewItem);
                }
                return result;
            });
        }

So that the amount of things done by the WebClient.SwitchView() method, to make sure to interact well with your Dynamics 365 page. Will all similar methods that exist, that's a lot of time and effort saved, isn't it ?

 

Dynamics 365 EasyRepro hands-on (Tutorial)

Retrieve the source code

Now let's see in a quick tutorial how to put your hands on EasyRepro.

First, go to the Github of the framework: https://github.com/microsoft/EasyRepro

Clone or download it. Open the Visual Studio solution. Build you solution and restore the nugget packages. It will retrieve everything you need, including Selenium.

You will find 4 projects in the solution:

EasyRepro Solution Explorer 2

The first 3 projects above contain the Dynamics 365 EasyRepro code.

The 4th project, "Microsoft.Dynamics365.UIAutomation.Sample" is a testing project. It contains dozens of testing scripts. In this project, the folder "UCI" contains sample tests for the new User Interface. And the folder "Web" contains sample tests for the classic (old) User Interface.

Don't hesitate to explore these 4 projects. It is a great way to discover EasyRepro and understand how it works.

 

Install the right driver for your browser

If you run a test now (one among the samples for instance), you might have an exception telling you that your Web Driver is not compatible with your browser. So you will need to get the right Web Driver.

In that case, first retrieve the version of your browser. If you use Chrome (as me), click the "three dots" button in the top right corner of the browser and click "Help" -> "About Google Chorme":

Dynamics 365 EasyRepro

Then download the driver corresponding to your Chrome version in this page: https://chromedriver.chromium.org/downloads

And finally just copy-paste the executable of the driver (chromedriver.exe) in the bin folder of your project (replacing the default Web Driver that didn't match your browser).

 

Launch your first test

And this is time to run your first test.

Go to the app.config file. Enter the URL of your CRM and the credentials to use by EasyRepro:

Dynamics 365 EasyRepro

The Dynamics 365 EasyRepro script will land on this URL. You can provide the root page URL of your CRM, or directly provide a deeper URL page.

That's it, you can open the Test explorer and run your first EasyRepro test.

Test explorer

And already have fun with the samples provided. You may enjoy seeing your browser controlled by your script.

 

Let's explore it further

Now, to explore EasyRepro together, let's have a look at a sample script I wrote. As said in the introduction, the script's goal would be to test the process of Lead creation until the Closing of the Opportunity. It is really a simple sample. The idea is more to give an idea of the potential of the Framework.

Here are the steps that I implemented:

  • Open the URL of your CRM (root page in that test sample)
  • Log into the CRN using the provided credentials
  • Open the Area "Sales" and then the Sub-Area "Leads"
  • Click "New"
  • Think for 5 seconds (imitate user!)
  • Enter some values in the Form
  • Save the Form
  • Get the value of the field "Type"
  • Check that the value of the "Type" is "Item based". That could for instance be your expected default value. If the value is not that, the test will fail.
  • Select the stage "Qualify" in the Lead
  • Enter some information in the fields
  • Save the Lead
  • Qualify the Lead (an Account, a Contact and an Opportunity are created. The Opportunity Form opens)
  • In the Opportunity, go to the next stage
  • In the timeline, click new Email
  • Add thanks for the interest in the subject
  • Send the email and close it (it brings back to the Opportunity Form)
  • Go to the next stage
  • Close the Opportunity as Won
  • In the dialog, enter information

The test will success if all steps could be performed.

If one step could not be executed, the test will fail and you will know something is wrong in your CRM.

 

Below is the EasyRepro script. There is not much to explain. You can easily match the lines of the code with the description of the steps above!

        public void UCITestLeadProcess()
        {
            var client = new WebClient(TestSettings.Options);
            using (var xrmApp = new XrmApp(client))
            {
                xrmApp.OnlineLogin.Login(_xrmUri, _username, _password, _mfaSecretKey);

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

                xrmApp.CommandBar.ClickCommand("New");

                xrmApp.ThinkTime(5000);

                xrmApp.Entity.SetValue("subject", "EasyRepro - Automated Testing for D365");
                xrmApp.Entity.SetValue("firstname", "Amaury");
                xrmApp.Entity.SetValue("lastname", "Veron");

                xrmApp.Entity.SetValue("companyname", "ELCA");
                xrmApp.Entity.SetValue("websiteurl", "https://dynamics-chronicles.com/");

                xrmApp.Entity.Save();

                string ordertype = xrmApp.Entity.GetValue(new OptionSet { Name = "msdyn_ordertype" });
                Assert.AreEqual(ordertype, "Item based");

                xrmApp.BusinessProcessFlow.SelectStage("Qualify");

                xrmApp.BusinessProcessFlow.SetValue("description", "Looking for automated testing");
                xrmApp.BusinessProcessFlow.SetValue("budgetamount", "50000");

                xrmApp.Entity.Save();

                xrmApp.CommandBar.ClickCommand("Qualify");

                xrmApp.BusinessProcessFlow.NextStage("Develop");

                xrmApp.Timeline.ClickEmailMenuItem();

                xrmApp.Timeline.AddEmailSubject("Many thanks for your interest. Let's go on.");
                xrmApp.Timeline.SaveAndCloseEmail();

                xrmApp.BusinessProcessFlow.NextStage("Propose");

                xrmApp.CommandBar.ClickCommand("Close as Won");

                xrmApp.Dialogs.CloseOpportunity(123.45, DateTime.Now, "Great project, let's go");

                xrmApp.ThinkTime(20000);
            }
        }

 

I have captured the execution of the test (and reduced it for size reasons), you can find it in the animation below.

It looks like a basic utilisation of the CRM... Except everything is controlled by your script, there is no human using the CRM.

Animation Automated process

 

 

D365 functionalities covering

Dynamics 365 EasyRepro covers a lot of Dynamics 365 features. Below is a list of the functionalities covered or uncovered. This list comes from the README.md file of the Github.

CRM Functionality Covered

  • Activity Record Wall
  • Business Process Flow
  • Charts
  • Commandbar
  • Dashboards
  • Entities (Create, Update, Delete, Duplicate Detection, Assign)
  • Global Search
  • Guided Help
  • Grids
  • Sub-Grids
  • Navigation
  • Notifications
  • Performance Center
  • Quick Create
  • Run Workflows
  • Run Reports

CRM Functionality Not Covered

  • Settings Area (Administration)
  • Customization
  • Advanced Find Query execution(Open Advanced Find is available)
  • Export to Excel
  • Templates
  • Other Add on Applications

 

You can find the reference of the framework in the Github: https://github.com/microsoft/EasyRepro/blob/develop/Documentation.md

It contains the available methods with expected parameters and outputs. It will also help you have an idea of all the functionalities of the framework.

The reference is not perfectly complete. For instance the method BusinessProcessFlow.SetValue() that I used in the sample test is not present in the reference (at the time I am writing this). But that is another good reason to explore the source code and the samples provided.

 

Important Note:

If some features you need are not covered yet in EasyRepro, you can still create your own function based on Selenium.

 

Conclusion

Here were the main things to know about EasyRepro. Hope you enjoy it and that you will have the opportunity to put your hands on it.

Test scripts obviously take some time to put in place. EasyRepro is easy to hold and scripts are quick to write. So I hope you might find it useful in projects with frequent releases and many features to check !

 

If you want to read more about testing (or deployment), don't hesitate to check our other Chronicles on the testing topic:

Dynamics 365 EasyRepro

Comments

Have you had any luck navigating around the Dynamics365 UI with EasyRepro when *NOT* using the English UI language?

E.g. the first step in the "CreateNewAccount" sample method spells out:

xrmBrowser.Navigation.OpenSubArea("Sales", "Accounts");

in the original source code. Since my UI is all in German, of course this is *NOT* spelled that way...... the area for me is called "Adressen" (for addresses for both accounts and contact), and then there's "Firmen" (accounts) - but when I change it to :

xrmBrowser.Navigation.OpenSubArea("Adressen", "Firmen");

the automated test does the login successfully and all - but then just sits there and doesn't go any further......

Do we need to use the GUIDs for the area and subareas? Using the English names doesn't work - tried that already. Or is there something else that's causing problems here?? Any inputs??

Mon, 08/02/2021 - 10:44
Marc Scheuner … (not verified)

Hello Marc,

No unfortunately I never used it with another language than English.

It is weird, I think you are doing it right. I had a look at the Source Code. It looks like you are using the parameters in the OpenSubArea() method just as needed. It is not expecting GUIDs.

Maybe you could try to debug your code step by step and see what happens inside the OpenSubArea() method. And check it is coherent with the HTML code you have in your browser.

Do you have the issue only with this method, or with all methods?

Thanks for your interest in the subject :D, Best regards

Tue, 08/17/2021 - 17:25

In reply to by Marc Scheuner … (not verified)

Add new comment

Image CAPTCHA
Enter the characters shown in the image.