Friday 16 August 2013

Using Selenium with Microsoft Dynamics CRM 2011

Earlier this week I was asked to look at the possiblity of using Selenium with Microsoft Dynamics CRM 2011 since it now supports Firefox (nothing like a clued up Test manager). At any rate, I thought I would give it a try.

The problem was that recording tests with the Selenium IDE wasn't not working as I was hitting constant javascript errors, so I decided to use the IDE as some sort of guidance and then modify the code generated to get it to work.

The test test [sic.] was to generate an entity (change) off another (callback) and then check that depending on the change type (field pre_type) various workflows and/or plugins would trigger.

Why this needed doing with Selenium it's beyond me, but there you go.

I won't go into details about the entities, but suffice to say that callback is the main entity in the system, there is a 1:N relationship between callback and change and changes can be created from the callback form.

So, I installed Selenium, downloaded the IE driver and got coding:

using System.Text;

using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Support.UI;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            IWebDriver driver = new InternetExplorerDriver(@"C:\Users\john\Downloads\selenium-dotnet-2.32.1\IEDriverServer_Win32_2.32.3\");
            driver.Url = "https://devcrm.dev.local//main.aspx?skipNotification=1";
            driver.FindElement(By.CssSelector("#pre_callback > nobr.ms-crm-NavBar-Subarea-Title")).Click();

            driver.SwitchTo().Frame("contentIFrame");

            driver.FindElement(By.Id("crmGrid_findCriteria")).Clear();
            driver.FindElement(By.Id("crmGrid_findCriteria")).SendKeys("*William*");
            driver.FindElement(By.Id("crmGrid_findCriteriaButton")).Click();

            driver.FindElement(By.Id("gridBodyTable_primaryField_{B2C895DC-DEAD-BEEF-9B08-F05056B2009F}_0")).Click();

            WaitForNewWindow(driver, 2);
            driver.SwitchTo().Window(driver.WindowHandles[1]);
            driver.SwitchTo().Frame("contentIFrame");

            driver.FindElement(By.Id("nav_pre_pre_callback_pre_change")).Click();
            driver.SwitchTo().DefaultContent();

            driver.FindElement(By.Id("pre_change|OneToMany|SubGridAssociated|Mscrm.SubGrid.pre_change.AddNewStandard-Large")).Click();

   WaitForNewWindow(driver, 3);

            driver.SwitchTo().Window(driver.WindowHandles[2]);
            driver.SwitchTo().Frame("contentIFrame");
            driver.FindElement(By.Id("DateInput")).SendKeys(DateTime.Now.ToString("dd/MM/yyyy"));
            driver.FindElement(By.Id("pre_changedetails")).SendKeys("Selenium Attack");
            
   for(int i=1; i < 6; i++
   {
                 SelectDropDown(driver, "pre_type", i);
                 driver.SwitchTo().DefaultContent();
                 driver.FindElement(By.Id("pre_change|NoRelationship|Form|Mscrm.Form.pre_change.SaveAndClose-Large")).Click();
   }
            driver.Quit();

        }

        private static void WaitForNewWindow(IWebDriver driver, int windowNumber)
        {
            while (driver.WindowHandles.Count != windowNumber)
            {
                Thread.Sleep(133);
            }
        }

        private static void SelectDropDown(IWebDriver driver, string fieldName, int selection)
        {
            IWebElement sourceWeb = driver.FindElement(By.Id(fieldName));
            SelectElement source = new SelectElement(sourceWeb);
            source.SelectByIndex(selection);
        }
    }
}

There is no reason why this could not be done as a unit test, but I thought it would be easier to distribute to the testers as a console app (It does need a lot of work, I know)

I have to say that I found it extremely flaky, in fact it seemed to need two runs, one to warm up and then it would almost always work.

Since, I haven't used Selenium much, I can't say how reliable or otherwise it is, but using the IE driver was not found suitable for testers.

I think it can be used for early morning checks and things like that but not for automated testing, all in all it was a big disappointment.

8 comments:

  1. Hi.. I have just one question. The login to MS Dynamics CRM comes up as a windows login component. How did you manage to get through the login screen?

    ReplyDelete
    Replies
    1. you can use autoit scripts to get in

      Delete
    2. This comment has been removed by the author.

      Delete
    3. We were using Claims based authentication so I was already logged in.

      Delete
    4. Hi Manyroots, you mentioned in the start of the blog that "Why this needs to be done with selenium beats me", i am new to the CRM dynamics scene and would be glad to know the alternative tools to test entities and workflows. It would be nice if you could point me in the direction for best practices for testing a CRM dynamics solution (automation)

      Delete
  2. Thanks everyone for your comments. We are yet to try out using AutoIT scripts to get through the Login. However, as of now we login to MS CRM manually for the first time, and then run our scripts, so that we are automatically logged-in everytime we hit the URL.

    ReplyDelete
  3. I was able to login into the Dynamics CRM page using selenium IDE but after then i got stuck and left with no option but to search for the solution and look for options

    ReplyDelete
  4. Hi, I am trying to automate Dynamics CRM. But i am not able to figure out to create new lead option . +NEW button on ribbon. It is giving elemnet not found exception

    ReplyDelete