Friday, 24 January 2014

Dynamics CRM Load and Web Performance Testing

Testing... the bit that comes at the end of every project! The one part which makes you realise how everything you have built and convinced yourself is running exactly how it should, may not be the case...

Recently after deploying a new customised CRM 2011 platform, the topic of load and performance testing came up. Not something that would normally need to be tested on a fully vetted of the shelf product, but still useful to show a working model of the infrastructure and application under load.

After some digging around I decided in this particular case, for an on premise deployment with custom entities, that custom tests would be most beneficial.

Requirements

In order to take advantage of the testing features offered by Visual Studio, a copy of the Ultimate version is required. Using a trial version you can simulate up to 250 users in a load test, any more than this and you will need the licensed product. In this case I have used Visual Studio 2013 Ultimate.

Actions

The following actions were taken to complete testing:

  • Create a Web Performance and Load Test project
  • Create a new Web Performance Test (CRM UI)
  • Create Unit Tests for data manipulation (CRM WCF)
  • Create a Load Test, incorporating the tests already created.

Web Performance and Load Testing


Firstly in VS you will need to create a new project:

File > New > Project > In the Test category, located under the Visual C# category, you should find Web Performance and Load Test Project:



Web Performance Test


In your newly created project you should see a Web Test already created for you, if not you can add this into your project by right clicking the project in the Solution Explorer on the right.

You can use this test if you want to simulate traffic to the CRM Web UI, e.g. A user opening up a browser and navigating to http://<CRM_Server>:<port>/<Organisation>.

To create the web test, you will see the "Add Recording" button at the top hand pane of this page in your project:


Once you have enabled the plugin for Internet Explorer, this will record the sites you visit via the browser and all web resources loaded from the server:



Unit Test


In order to simulate records being created and removed from the CRM application, I decided to create separate tests, this was achieved using the CRM WCF Endpoint. This is particularly useful to integrate with all the CRM metadata, meaning that you can work with custom entities as well as standard, supporting both late-bound and early-bound types.

Create a new Unit Test in your project by right clicking the project in the Solution Explorer on the right, selecting Add > Unit Test...

Below is an example test written to create and remove accounts in CRM, you may want to write more of your own to test custom entities:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xrm.Sdk;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using System.Configuration;

namespace CRMLoadTest
{
    [TestClass]
    public class AccountTest
    {
        private IOrganizationService orgService { get; set; }
        private ClientCredentials _ClientCreds { get; set; }

        private Guid resultId { get; set; }

        [TestInitialize]
        public void SetUp()
        {
            orgService = null;
            Uri uri = new Uri(ConfigurationManager.AppSettings.Get("orgWcfService"));
            IServiceConfiguration orgConfigInfo =
                ServiceConfigurationFactory.CreateConfiguration(uri);

            orgService = new OrganizationServiceProxy(orgConfigInfo, _ClientCreds);
        }

        [TestMethod]
        public void CreateAccount()
        {
            //arrange
            var account = new Entity("account");
            account.Attributes.Add("name", string.Format("Unit Test {0}", DateTime.Now));

            //act
            resultId = orgService.Create(account);

            //assert
            var createdAccount = orgService.Retrieve("account", resultId, new ColumnSet(new[] { "accountnumber" }));
            Assert.IsNotNull(createdAccount.GetAttributeValue("accountnumber"));
        }

        [TestCleanup]
        public void RemoveAccount()
        {
            orgService.Delete("account", resultId);
        }
    }
}


As you can see above on line 23, I am pulling the endpoint URL from an app.config file. This is to be able to easily change the server for the tests without manually editing each test. The App.config file I have created looks like the below [optional]:

 <?xml version="1.0" encoding="utf-8" ?>
  <configuration>
    <appSettings>
      <add key="orgWcfService" value="http://crm01/CRM/XRMServices/2011/Organization.svc"/>
    </appSettings>
  </configuration>

Remember you can create as many tests as you like to be added to your load test.


Load Test


Now you have created the above tests, we can add these together into a load test. The load test gives you the ability to simulate multiple users all running these tests at once.

The Web Performance Test coupled with the Unit Tests you have written would not only produce many users loading the CRM Web UI, but also produce many users all creating and deleting records as well.

To create a new test, right click your project as you did before in the Solution Explorer and select Add > Load Test... Using the wizard provided you can now set conditions for you load test, such as:

User Count

Setting the amount of users that will be simulated when running your tests.


Test Mix

Here you will add your tests and choose your distribution between them.


Counter Sets

A particularly useful feature to be able monitor the performance of the application servers while the load test is run.



Output

Once you have completed and ran the Load Test you will have a visual output of all counters monitored, as well as statistics of the tests performed:




Hopefully this post has been useful and inspired some ideas when it comes to load testing your infrastructure and applications.



Tuesday, 21 January 2014

Hyper-V Development Environment

Hyper-V Networking Set up


Recently I decided to make the long outstanding change from VMWare to Hyper-V as a development environment using Windows 8.1, after all it made sense to try it out! Installing Hyper-V with Windows 8 was dead simple, turn on the feature in Programs and Features, reboot the machine and you're done... make sure you have virtualization enabled in your BIOS of course.

This post should give you a quick walk-through of the set-up process. I have created a domain controller of which I do not want to have internet access or to be able to communicate with the network outside of the host. Then I created servers which I do want to have internet access, but still be able to talk to the domain controller. This environment in particular is a Dynamics CRM server set-up, however this will work for any windows server's and the set-up process is the same. 

Environment:
  • Internal Virtual Switch (192.168.10.2)
  • External Virtual Switch
  • Domain controller (DC01 / 192.168.10.10)
  • CRM Server (CRM01 / 192.168.10.20)
  • SQL Server (SQL01 / 192.168.10.30)

Great! so now you have Hyper-V installed what next?... Create VMs right?


This is where I came a little unstuck with the standard Hyper-V set-up. Now you need to create a virtual switch for your virtual machines to talk to, but maybe like me you only want certain VMs to communicate out to the internet, whilst still being able to RDP to all VMs from the host. Some people to achieve this take the approach of turning the host machine into a domain controller, to me this does not seem practical and of course, there is always an easier solution.

Virtual Switches

So first things first! We need to sort out our virtual switches, one for internal communication on the V-LAN and the other for external communication out to the internet.

Once you have loaded up the Hyper-V Manager console you should see the Virtual Switch Manager in the right hand pane, in here you will be able to create the two needed switches, an internal switch and an external.

The external switch will need to be assigned to your physical NIC in the host machine as so:


The internal switch will look like the below:


Once you have created these virtual switches, you should see them listed as adapters on your host machine. Now we need to give the Internal Switch adapter a static IP, for this example I have used the following IP address: 192.168.10.2. You can leave the default gateway and DNS Servers blank, as this is just an internal V-LAN.



Our virtual switches should now be all set-up, the external switch requires no static IP, this will just act as the gateway to the internet.

Virtual Machines!


Now we have got our virtual switches all set-up, it's time to create our virtual machines. Now in this example I am using Windows Server 2008 R2 as the server OS but the principal is the same in Server 2012

Domain Controller

First is the domain controller. Now this server I do not want to be able to communicate out to the internet and the network outside of my host machine. This server should only talk across the V-LAN.

To achieve this we only assign one network adapter to the VM, which is connected to the internal switch:



Once logged onto the domain controller we assign it a static IP, I have pointed the DNS at itself (local loopback) as this server will run the DNS role as well:


Servers (CRM, SharePoint, anything not a domain controller!)

Domain controller up and running, now ready for the rest! The rest of my servers I do want to be able to connect to the internet for windows updates and things like making the install process for CRM a lot easier.

In order for this to happen the VM will need to have two virtual network adapters assigned to it, one connected to the internal network and the other connected to the external network, this is shown below for my CRM server:


Now that you have these connected, like the domain controller, we can assign a static IP to the adapter connected to the internal switch. If you cannot recognise what adapter is connected to what switch go back and disconnect the external adapter for a moment while we assign the IP. For my CRM server I have given this the following IP: 192.168.10.20


Note: As seen in the screenshot above, I have set the DNS server to be the IP address of the domain controller (as it runs the DNS role). This is important for joining the server to the domain, and also finding other servers in the domain. If you have not installed DNS on your domain controller then you will need to point the DNS at your DNS server. You can also add the host name and FQDN of the domain controller to the servers host file.

Now your server should be set-up to communicate with other virtual machines on the internal switch and also out to the internet via the external switch.

RDP from Host

One final change I made was to my host file on my Windows 8.1 host Hyper-V machine. In order to RDP to the servers on the internal switch, the IP address would have to be used. This is because the Hyper-V host does not use the domain controller VM for it's DNS, in my case the host looks at Google DNS as my preference.

To resolve this issue the hostname, FQDN and IP of the servers needs to be added to the host file located here:

C:\Windows\System32\drivers\etc\hosts

Note: When editing the host file, ensure you are running notepad with elevated privileges in order to save the system file back to it's original location.


Now the development environment should be all set-up, you can repeat the "Servers" process assigning static IPs and DNS to any more servers you create and joining them to your domain.