Automated UI Testing Using EasyRepro

Loading

1. Introduction to EasyRepro for Dynamics 365 Testing

What is EasyRepro?

EasyRepro is an open-source test automation framework specifically designed for Microsoft Dynamics 365 applications. Developed by Microsoft engineers, it provides:

  • C#-based testing library for Dynamics 365 CE/F&O
  • Selenium WebDriver integration
  • Pre-built methods for common CRM operations
  • Cross-browser testing capabilities

Why Use EasyRepro Over Generic Testing Tools?

Native Dynamics 365 element locators
Optimized wait handlers for async processes
Built-in XPath generators for CRM controls
Active community support (GitHub, MS Docs)

2. Technical Architecture

Core Components

graph TD
    A[Test Scripts] --> B[EasyRepro API]
    B --> C[Selenium WebDriver]
    C --> D[Browser]
    D --> E[Dynamics 365]

Supported Technologies

  • Languages: C# (.NET Core/.NET 5+)
  • Testing Frameworks: MSTest, NUnit, xUnit
  • CI/CD: Azure DevOps, GitHub Actions
  • Reporting: ExtentReports, Allure

3. Environment Setup

Prerequisites

  1. Development Environment:
  • Visual Studio 2019/2022
  • .NET 5+ SDK
  1. Testing Tools:
  • Selenium WebDriver
  • Browser drivers (Chrome, Edge, Firefox)
  1. Dynamics 365 Access:
  • Test environment URL
  • Service account credentials

Installation Steps

# Clone the repository
git clone https://github.com/microsoft/EasyRepro

# Install NuGet packages
dotnet add package Microsoft.Dynamics365.UIAutomation.Api
dotnet add package Selenium.WebDriver

4. Writing Your First Test

Basic Test Structure

[TestClass]
public class AccountTests : TestBase
{
    [TestMethod]
    public void CreateNewAccount()
    {
        using (var client = new WebClient(TestSettings.Options))
        {
            // Login to D365
            client.Browser.LoginPage.Login(
                TestSettings.Username, 
                TestSettings.Password);

            // Navigate to Accounts
            client.Browser.Navigation.OpenSubArea("Sales", "Accounts");

            // Create new account
            client.Browser.CommandBar.ClickCommand("New");

            // Set field values
            client.Browser.Entity.SetValue("name", "Test Account");
            client.Browser.Entity.SetValue("telephone1", "555-1234");

            // Save and verify
            client.Browser.CommandBar.ClickCommand("Save");
            Assert.IsTrue(client.Browser.Entity.GetValue("name") == "Test Account");
        }
    }
}

Key Methods

MethodPurposeExample
Login()Authenticate to D365Login(username, password)
SetValue()Populate fieldsSetValue("fieldname", value)
GetValue()Read field valuesGetValue("fieldname")
ClickCommand()Toolbar actionsClickCommand("Save & Close")

5. Advanced Testing Scenarios

Handling Complex UI Elements

// Working with lookups
client.Browser.Entity.SelectLookup("primarycontactid");
client.Browser.Lookup.Search("John Doe");
client.Browser.Lookup.Add();

// Dealing with business process flows
client.Browser.BPF.SelectStage("Qualify");
client.Browser.BPF.NextStage();

// Testing dialogs
client.Browser.Dialogs.ConfirmationDialog(true);

Data-Driven Testing

[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", 
    "TestData\\Accounts.csv", "Accounts#csv", DataAccessMethod.Sequential)]
[TestMethod]
public void CreateAccount_DataDriven()
{
    var accountName = TestContext.DataRow["Name"].ToString();
    var phone = TestContext.DataRow["Phone"].ToString();

    client.Browser.Entity.SetValue("name", accountName);
    client.Browser.Entity.SetValue("telephone1", phone);
}

6. Best Practices for Reliable Tests

Element Locator Strategies

  1. Prefer API methods over direct XPath
   // Good
   client.Browser.Entity.SetValue("name", "Acme");

   // Avoid
   driver.FindElement(By.XPath("//input[@aria-label='Account Name']"));
  1. Custom wait handlers for Dynamics controls
   client.Browser.Driver.WaitUntilClickable(
       By.XPath("//button[@title='Save']"), 
       TimeSpan.FromSeconds(30));

Test Stability Techniques

  • Retry mechanisms for flaky tests
  • Environment checks before execution
  • Screenshot capture on failures

7. Integration with CI/CD Pipelines

Azure DevOps Example

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    projects: '**/*Tests.csproj'
    arguments: '--configuration Release --collect "Code coverage"'

- task: PublishTestResults@2
  inputs:
    testResultsFormat: 'VSTest'
    testResultsFiles: '**/*.trx'

Parallel Execution Setup

[AssemblyInitialize]
public static void Setup(TestContext context)
{
    TestSettings.Options = new BrowserOptions
    {
        BrowserType = BrowserType.Chrome,
        Headless = true,
        RemoteBrowser = false,
        UCITestMode = true,
        DriversPath = @"C:\WebDrivers"
    };
}

8. Reporting and Analysis

Generating HTML Reports

[TestInitialize]
public void Init()
{
    _extent = new ExtentReports();
    _test = _extent.CreateTest(TestContext.TestName);
}

[TestCleanup]
public void Cleanup()
{
    var status = TestContext.CurrentTestOutcome;
    _test.Log(status, "Test completed");
    _extent.Flush();
}

Interpreting Test Results

  • Failure analysis: DOM snapshots vs. test steps
  • Performance metrics: Page load times
  • Environment logging: Browser versions, URLs

9. Common Challenges and Solutions

ChallengeSolution
IFrame detection issuesUse SwitchToDefaultContent()
Random popupsImplement dismissal handlers
Async save operationsCustom wait conditions
MFA requirementsUse test accounts without MFA

10. Future of Dynamics 365 Testing

Upcoming Features

  • Power Platform test automation integration
  • AI-powered test maintenance
  • Codeless test authoring

Community Resources

Implementation Roadmap

  1. Pilot Phase (2-4 weeks)
  • Setup test infrastructure
  • Create 10-20 core test cases
  • Integrate with build pipeline
  1. Expansion Phase (1-3 months)
  • Cover critical business processes
  • Implement data-driven testing
  • Add CI/CD integration
  1. Maturity Phase (Ongoing)
  • Maintenance strategy
  • Test coverage metrics
  • Flaky test management

Pro Tip: Start with happy path scenarios before tackling edge cases, and always include test data cleanup in your automation.

// Example cleanup method
[TestCleanup]
public void Cleanup()
{
    try 
    {
        if (TestContext.CurrentTestOutcome == UnitTestOutcome.Passed)
        {
            client.Browser.Entity.Delete();
        }
    }
    catch { /* Log error */ }
}

Leave a Reply

Your email address will not be published. Required fields are marked *