Monday, July 15, 2013

Data Import using Visual Studio Test Framework

<!--[if !mso]><![endif]     
Data Import using Visual Studio Test Framework
 
Purpose: The purpose of this document is to illustrate how to use Visual Studio Test Framework to import data into Microsoft Dynamics AX 2012
 
Challenge: For the purposes of POC (Proof of Concept) or testing in you need to import business data into Microsoft Dynamics AX 2012 with minimum effort without knowing the specifics of the data model and business logic, you can do it via User Interface with help of Visual Studio Test Framework
 
Solution: Using Microsoft Visual Studio Test Project you can create a Coded UI Test that tests whether the User Interface for an application functions correctly. Coded UI Test performs actions on the user interface controls for an application and verifies that specified controls display the correct values. However in this scenario we’ll use coded UI test, specifically Data Driven Coded UI Test, to automate tedious manual task of entering the data into the system via User Interface
 
Diagram

 
Walkthrough: Data Driven Coded UI Test
 
Create Test project
 
 
TestProject1
 
 
Add Coded UI Test
 
 
Generate Code for Coded UI Test: Record actions, edit UI map or add assertions
 
 
Coded UI Test Builder
 
 
Start recording
 
 
Now we will go through the usual process of customer creation in Microsoft Dynamics AX 2012 while recording all the actions
 
You can pause recording and then resume it if required
 
 
 
Once done we’ll give a name to the method. For example, CustomerImport
 
 
You can record actions for more methods if required. For example, for import of vendors, etc 
 
 
The system will generate all necessary code for you
 
 
Source code
 
public void CustomerImport()

{

    #region Variable Declarations

    WinMenuItem uICustomerMenuItem = this.UIMicrosoftDynamicsAXDWindow.UIHomeTabWindow.UINewGroup.UICustomerMenuItem;

    WinEdit uINameEdit = this.UICustomer1usmfNewRecoWindow.UIItemWindow.UINameEdit;

    WinClient uICustomergrouplookupbClient = this.UICustomer1usmfNewRecoWindow.UIItemWindow1.UICustomergrouplookupbClient;

    WinCell uIItem10Cell = this.UIItem1usmfWindow.UIItemWindow.UIGridTable.UIRow1Row.UIItem10Cell;

    WinButton uISaveandcloseButton = this.UICustomer1usmfNewRecoWindow.UIItemWindow2.UISaveandcloseButton;

    #endregion

 

    // Click 'Customer' menu item

    Mouse.Click(uICustomerMenuItem, new Point(35, 40));

 

    // Click 'Name' text box

    Mouse.Click(uINameEdit, new Point(23, 0));

 

    // Type 'Alex Customer' in 'Name' text box

    uINameEdit.Text = this.CustomerImportParams.UINameEditText;

 

    // Click 'Customer group lookup button' client

    Mouse.Click(uICustomergrouplookupbClient, new Point(4, 8));

 

    // Click '10' cell

    Mouse.Click(uIItem10Cell, new Point(43, 11));

 

    // Click 'Save and close' button

    Mouse.Click(uISaveandcloseButton, new Point(66, 10));
}
 



[GeneratedCode("Coded UITest Builder", "10.0.40219.445")]

public class CustomerImportParams

{

   

    #region Fields

    /// <summary>

    /// Type 'Alex Customer' in 'Name' text box

    /// </summary>

    public string UINameEditText = "Alex Customer";

    #endregion
}
 
 

XML

<?xml version="1.0"?>
<UITest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="" Id="d7c9b5a2-9a9b-4562-a65e-678e9d87ba78" AssemblyVersion="10.0.40219.445" Version="1.0" xmlns="http://schemas.microsoft.com/VisualStudio/TeamTest/UITest/2010">
  <Configuration>
    …
  <Configuration />
  <InitializeActions />
  <ExecuteActions>
    <MouseAction UIObjectName="UIMap.UIMicrosoftDynamicsAXDWindow.UIHomeTabWindow.UINewGroup.UICustomerMenuItem">
      <ParameterName />
      <ModifierKeys>None</ModifierKeys>
      <IsGlobalHotkey>false</IsGlobalHotkey>
      <Location X="35" Y="40" />
      <WheelDirection>0</WheelDirection>
      <ActionType>Click</ActionType>
      <MouseButton>Left</MouseButton>
    </MouseAction>
    <MouseAction UIObjectName="UIMap.UICustomer1usmfNewRecoWindow.UIItemWindow.UINameEdit">
      <ParameterName />
      <ModifierKeys>None</ModifierKeys>
      <IsGlobalHotkey>false</IsGlobalHotkey>
      <Location X="23" Y="0" />
      <WheelDirection>0</WheelDirection>
      <ActionType>Click</ActionType>
      <MouseButton>Left</MouseButton>
    </MouseAction>
    <SetValueAction UIObjectName="UIMap.UICustomer1usmfNewRecoWindow.UIItemWindow.UINameEdit">
      <ParameterName />
      <Value Encoded="false">Alex Customer</Value>
      <Type>String</Type>
    </SetValueAction>
    <MouseAction UIObjectName="UIMap.UICustomer1usmfNewRecoWindow.UIItemWindow1.UICustomergrouplookupbClient">
      <ParameterName />
      <ModifierKeys>None</ModifierKeys>
      <IsGlobalHotkey>false</IsGlobalHotkey>
      <Location X="4" Y="8" />
      <WheelDirection>0</WheelDirection>
      <ActionType>Click</ActionType>
      <MouseButton>Left</MouseButton>
    </MouseAction>
    <MouseAction UIObjectName="UIMap.UIItem1usmfWindow.UIItemWindow.UIGridTable.UIRow1Row.UIItem10Cell">
      <ParameterName />
      <ModifierKeys>None</ModifierKeys>
      <IsGlobalHotkey>false</IsGlobalHotkey>
      <Location X="43" Y="11" />
      <WheelDirection>0</WheelDirection>
      <ActionType>Click</ActionType>
      <MouseButton>Left</MouseButton>
    </MouseAction>
    <MouseAction UIObjectName="UIMap.UICustomer1usmfNewRecoWindow.UIItemWindow2.UISaveandcloseButton">
      <ParameterName />
      <ModifierKeys>None</ModifierKeys>
      <IsGlobalHotkey>false</IsGlobalHotkey>
      <Location X="66" Y="10" />
      <WheelDirection>0</WheelDirection>
      <ActionType>Click</ActionType>
      <MouseButton>Left</MouseButton>
    </MouseAction>
    <TestStepMarkerAction MarkerInformation="CustomerImport">
      <ParameterName />
      <StepId>-1</StepId>
      <Direction>Start</Direction>
      <Outcome />
      <Disabled>false</Disabled>
      <WorkItemId>0</WorkItemId>
      <MarkerRegionType>Action</MarkerRegionType>
   </TestStepMarkerAction>
  </ExecuteActions>
  <CleanupActions />
  <OnErrorActions />
  <Maps>
    … 
  </Maps>
  <ValueMap>
    <ParameterList />
  </ValueMap>
</UITest>
 
Please note that XML will be different depending on how I enter a data. Below I describe a difference between using a lookup for data selection versus keying in the data
 
Option 1 – Lookup
 
<MouseAction UIObjectName="UIMap.UICustomer1usmfNewRecoWindow.UIItemWindow1.UICustomergrouplookupbClient">
  <ParameterName />
  <ModifierKeys>None</ModifierKeys>
  <IsGlobalHotkey>false</IsGlobalHotkey>
  <Location X="4" Y="8" />
  <WheelDirection>0</WheelDirection>
  <ActionType>Click</ActionType>
  <MouseButton>Left</MouseButton>
</MouseAction>
<MouseAction UIObjectName="UIMap.UIItem1usmfWindow.UIItemWindow.UIGridTable.UIRow1Row.UIItem10Cell">
  <ParameterName />
  <ModifierKeys>None</ModifierKeys>
  <IsGlobalHotkey>false</IsGlobalHotkey>
  <Location X="43" Y="11" />
  <WheelDirection>0</WheelDirection>
  <ActionType>Click</ActionType>
  <MouseButton>Left</MouseButton>
</MouseAction>
 
Option 2 – Key in
 
<SendKeysAction UIObjectName="UIMap.UICustomer1usmfNewRecoWindow.UIItemWindow.UINameEdit">
  <ParameterName />
  <ModifierKeys>None</ModifierKeys>
  <IsGlobalHotkey>false</IsGlobalHotkey>
  <Text Encoded="false">{Tab}</Text>
</SendKeysAction>
<SetValueAction UIObjectName="UIMap.UICustomer1usmfNewRecoWindow.UIItemWindow1.UICustomergroupEdit">
  <ParameterName />
  <Value Encoded="false">10</Value>
  <Type>String</Type>
</SetValueAction>
 
Now we can run the test and the system will create a customer for us
 

Result in Microsoft Dynamics AX 2012
 
 
We can technically create one more customer by changing the code appropriately
 
 
Source code
 


[GeneratedCode("Coded UITest Builder", "10.0.40219.445")]

public class CustomerImportParams

{

   

    #region Fields

    /// <summary>

    /// Type 'Alex Customer 2' in 'Name' text box

    /// </summary>

    public string UINameEditText = "Alex Customer 2";

    #endregion
}

    


Result in Microsoft Dynamics AX 2012
 
 
In fact we are interested in creating multiple customers at once
 
For these purposes we can introduce a loop
 
 
Source code



public void CustomerImport()

{

    #region Variable Declarations

    WinMenuItem uICustomerMenuItem = this.UIMicrosoftDynamicsAXDWindow.UIHomeTabWindow.UINewGroup.UICustomerMenuItem;

    WinEdit uINameEdit = this.UICustomer1usmfNewRecoWindow.UIItemWindow.UINameEdit;

    WinClient uICustomergrouplookupbClient = this.UICustomer1usmfNewRecoWindow.UIItemWindow1.UICustomergrouplookupbClient;

    WinCell uIItem10Cell = this.UIItem1usmfWindow.UIItemWindow.UIGridTable.UIRow1Row.UIItem10Cell;

    WinButton uISaveandcloseButton = this.UICustomer1usmfNewRecoWindow.UIItemWindow2.UISaveandcloseButton;

    #endregion

 

    int i;

 

    for (i = 2; i <= 10; i++)

    {

        // Click 'Customer' menu item

        Mouse.Click(uICustomerMenuItem, new Point(35, 40));

 

        // Click 'Name' text box

        Mouse.Click(uINameEdit, new Point(23, 0));

 

        // Type 'Alex CustomerN' in 'Name' text box

        uINameEdit.Text = this.CustomerImportParams.UINameEditText + i.ToString();

 

        // Click 'Customer group lookup button' client

        Mouse.Click(uICustomergrouplookupbClient, new Point(4, 8));

 

        // Click '10' cell

        Mouse.Click(uIItem10Cell, new Point(43, 11));

 

        // Click 'Save and close' button

        Mouse.Click(uISaveandcloseButton, new Point(66, 10));

    }
}
 
 
    




[GeneratedCode("Coded UITest Builder", "10.0.40219.445")]

public class CustomerImportParams

{

   

    #region Fields

    /// <summary>

    /// Type 'Alex Customer' in 'Name' text box

    /// </summary>

    public string UINameEditText = "Alex Customer";

    #endregion
}
 
 
    

Result in Microsoft Dynamics AX 2012
 
 
This approach will work if all our customers will have uniform/similar name
 
However when we really want to do is to import customers based on a file. For example, we have CSV (Comma Separated Value) file with a list of customers
 
For these purposes we will introduce Data Driven Coded UI Test
 
Please find more info about Data Driven Coded UI Test here: http://msdn.microsoft.com/en-us/library/ee624082.aspx
 
 
CSV File
 
Name
Alex Customer2
Alex Customer3
Alex Customer4
Alex Customer5
Alex Customer6
Alex Customer7
Alex Customer8
Alex Customer9
Alex Customer10
 
Source code
 


[DeploymentItem("Customers.csv"),

 DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV",

 "C:\\Users\\Administrator\\Documents\\Visual Studio 2010\\Projects\\TestProject\\TestProject\\Customers.csv", "Customers#csv",

 DataAccessMethod.Sequential),

 TestMethod]

public void CodedUITestMethod1()

{

    // To generate code for this test, select "Generate Code for Coded UI Test" from the shortcut menu and select one of the menu items.

    // For more information on generated code, see http://go.microsoft.com/fwlink/?LinkId=179463

    string name = TestContext.DataRow[0].ToString();

 

    this.UIMap.CustomerImport(name);
}

 


public void CustomerImport(string _name)

{

    #region Variable Declarations

    WinMenuItem uICustomerMenuItem = this.UIMicrosoftDynamicsAXDWindow.UIHomeTabWindow.UINewGroup.UICustomerMenuItem;

    WinEdit uINameEdit = this.UICustomer1usmfNewRecoWindow.UIItemWindow.UINameEdit;

    WinClient uICustomergrouplookupbClient = this.UICustomer1usmfNewRecoWindow.UIItemWindow1.UICustomergrouplookupbClient;

    WinCell uIItem10Cell = this.UIItem1usmfWindow.UIItemWindow.UIGridTable.UIRow1Row.UIItem10Cell;

    WinButton uISaveandcloseButton = this.UICustomer1usmfNewRecoWindow.UIItemWindow2.UISaveandcloseButton;

    #endregion

 

    // Click 'Customer' menu item

    Mouse.Click(uICustomerMenuItem, new Point(35, 40));

 

    // Click 'Name' text box

    Mouse.Click(uINameEdit, new Point(23, 0));

 

    // Type 'Alex Customer' in 'Name' text box

    uINameEdit.Text = _name;// this.CustomerImportParams.UINameEditText;           

 

    // Click 'Customer group lookup button' client

    Mouse.Click(uICustomergrouplookupbClient, new Point(4, 8));

 

    // Click '10' cell

    Mouse.Click(uIItem10Cell, new Point(43, 11));

 

    // Click 'Save and close' button

    Mouse.Click(uISaveandcloseButton, new Point(66, 10));        
}
  
Note: Please note that all changes to your test to enable it to use a data source for the parameters will be made to your test's source code file (i.e. CodedUITest1.cs). You cannot modify the code in the UIMap.Designer.cs file.
 
Result in Microsoft Dynamics AX 2012
 
 
Remark: Please note that in order for Coded UI Test to interact with desktop the computer running the test should not be locked during test execution time. Otherwise you will see the following error: “Automation engine is unable to playback the test because it is not able to interact with the desktop.  This could happen if the computer running the test is locked or its remote session window is minimized.”
 
Summary: This document describes how to use Visual Studio Test Framework to import data into Microsoft Dynamics AX 2012 for the purposes of POC or testing by automation of data entry via User Interface. You can organize parallel import of data by running multiple instances of the test at the same time from different clients or investigate how to potentially make use of Load Test Visual Studio Test Framework. Please note that the recommended tool for data import in Microsoft Dynamics AX 2012 is Data Import Export Framework which provides number of standard templates for main business entities and documents, ability to use various entity types (Entity, Composite Entity, Table) and extend it for custom data.     
 
Author: Alex Anikiev, PhD, MCP
 
Tags: Microsoft Dynamics ERP, Microsoft Dynamics AX 2012, Data Migration, Data Import, Data Conversion, Test Automation, Visual Studio Test Framework, Data Driven Coded UI Test.
Note: This document is intended for information purposes only, presented as it is with no warranties from the author. This document may be updated with more content to better outline the concepts and describe the examples.

3 comments:

  1. Thanks for this!!!

    BTW, this post doesn't seem to open in IE

    ReplyDelete
  2. Hi Beebe4!
    I use IE10 and can see all the content properly
    /Alex

    ReplyDelete