Tuesday, April 21, 2015

Managing your Azure infrastructure as code - part 1 (VM configuration)

Azure PowerShell is a powerful scripting environment that you can use to control and automate the deployment and management of your workloads in Azure. Using Azure PowerShell cmdlet architects and developers can automate every manual and repeated tasks on the Azure infrastructure. Nearly everything you can do manually in the Azure management portal can be done using Azure PowerShell in the Microsoft Azure Automation service. In this blog, we'll see how you can leverage the power of Azure PowerShell cmdlets to create Azure virtual machines with the platform images. To start with, the first step is to create a Azure virtual machine configuration object. The configuration object can be created using the New-AzureVMConfig cmdlets.

This object can then be used to perform a new deployment, as well as to add a new virtual machine to an existing deployment. To create a new virtual machine configuration, we’ll need a name for the virtual machine. We'll start the configuration object by specifying some initial characteristics. Later we'll modify the configuration object with the supporting cmdlets to create a VM. To start with, we'll need a valid name for the VM, the size for the virtual machine and the name of the image to use.
To list all the available worker role sizes you can use the cmdlets Get-AzureRoleSize as given below.

Get-AzureRoleSize | where { $_.SupportedByVirtualMachines -eq $true } | select instancesize

Choose a size from the listed options to use in the configuration.
Next, you’ll need a virtual image name, from the available options. You can use the cmdlet Get-AzureVMImage| Select imagename to list out the image names.
Using this information, you can create an initial configuration object like.

$vmName = “[YOUR_VM_NAME]”
$image = “[YOUR_VM_IMAGE_NAME]”
$azureVMConfig = New-AzureVMConfig -Name $vmName -InstanceSize ExtraSmall -ImageName $image

Next we'll use the Add-AzureProvisioningConfig cmdlet to add a provisioning configuration to the virtual machine. We'll use the Add-AzureProvisioningConfig cmdlet to modify the Azure VM configuration by setting the properties like admin credentials, data disk, endpoints, load balanced set etc. For e.g creating a Windows server, you can extend the command like.

$admin = "[ADMIN_USERNAME]"
$password = "[PASSWORD]"
$azureVM = New-AzureVMConfig -Name $vmName `
-InstanceSize ExtraSmall `
-ImageName $image `
| Add-AzureProvisioningConfig -Windows `
-AdminUsername $admin `
-Password $password

Next, we'll add a new data disk to the virtual machine object. The Add-AzureDataDisk cmdlet can be used to add a new data disk to a virtual machine object. We'll use the CreateNew parameter to create a new data disk with a specified size and label, and then attach it to the configuration. For e.g the below cmdlet Add-AzureDataDisk -CreateNew -DiskSizeInGB 200 -DiskLabel "datadisk1" -LUN 0 will create a new disk with name datadisk1 with an initial size of 200 GB with the logical unit number 0 in the data drive in the machine. We’ll use this details to extend our command like
$azureVM = New-AzureVMConfig -Name $vmName `
-InstanceSize ExtraSmall `
-ImageName $image | `
Add-AzureProvisioningConfig -Windows `
-AdminUsername $admin `
-Password $password | `
Add-AzureDataDisk -CreateNew `
-DiskSizeInGB 200 `
-DiskLabel "datadisk1" `
-LUN 0

Next we'll add a network endpoint to the virtual machine configuration using the Add-AzureEndpoint cmdlet. Endpoints in Windows Azure consist of a protocol, along with a public and private port. The private port is the port that the service is listening on the local computer. The public port is the port that the service is listening on externally. In some cases this is the same port, which is the case for PowerShell. The Add-AzureEndpoint cmdlet is used to add a new endpoint to an azure virtual machine or configuration. While adding an endpoint you can specify a new endpoint that is not load balanced, which will be used only by this virtual machine, or you can specify a load-balanced endpoint, which other virtual machines running in the same cloud service can share to load-balance traffic. You can also specify parameters for an endpoint probe. The probe will be used to check the health of endpoints and endpoint resources, probing for response every 15 seconds, and taking a resource out of rotation if no response is received within 31 seconds. For e.g the command Add-AzureEndpoint -Name "HTTP" -Protocol TCP -LocalPort 80 -PublicPort 80 -LBSetName "HttpLoadbalancedSet" –DefaultProbe will add an endpoint with name HTTP listening on public and private port 80 with default probe option. Let’s extend our command with this option too.

$azureVM = New-AzureVMConfig -Name $vmName `
-InstanceSize ExtraSmall `
-ImageName $image | `
Add-AzureProvisioningConfig -Windows `
-AdminUsername $admin `
-Password $password | `
Add-AzureDataDisk -CreateNew `
-DiskSizeInGB 200 `
-DiskLabel "datadisk1" `
-LUN 0 | `
Add-AzureEndpoint -Name "HTTP" `
-Protocol TCP `
-LocalPort 80 `
-PublicPort 80 -LBSetName "HttpLoadbalancedSet" `
–DefaultProbe

If you want to add more endpoints you can pipe more endpoints to the configurations based on your need. For e.g Add-AzureEndpoint -Protocol TCP -LocalPort 443 -PublicPort 443 -Name 'LBHTTPS' -LBSetName 'LBHTTPS' -ProbePort 443 -ProbeProtocol https -ProbePath '/'

Using this information, you can now create your VM by using a unique cloud service name like.

New-AzureVM -ServiceName [YOUR_CLOUD_SERVICE_NAME] -VMs $azureVM

Sunday, April 19, 2015

CodedUI - Attribute based page objects and Jquery selectors to find controls

In UI automation Page Object is a popular design pattern which helps you create UI tests that are easy to maintain and help reducing code duplication. The basic idea behind page objects is that you can create a page class that represents the complete HTML page under test in an object oriented way. For e.g. the controls on the HTML page will be represented by properties in the page class and actions as methods. By doing this it’s very easy to use the benefits of OOPS to create composable menus, headers, footers etc. to reuse those parts in the page objects. In short Page objects encapsulate the behaviors of the HTML page by exposing methods that reflects the user actions and hides the details of telling the browser how to do these things.
Attributes in C# provides a powerful method of associating declarative information in code (types, methods, properties, and so forth). Once associated with a program entity, the attribute can be queried at run time and used in many ways. We'll see how to use attributes in Page objects to provide information on how to find a control on the DOM and later use this in the UI tests. Also we'll see how to use the metadata from the attributes to create JQuery selectors and execute them on the page, using the BrowserWindow.ExecuteScript method to find controls on the page much faster.

Step 1: Creating custom attributes.

Page attribute:

The page attribute is used to provide information related to the page under test, for e.g we’ll use this attribute to provide details like the page url, browser information etc. A simple page attribute looks like.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PageAttribute : Attribute
{
    public PageAttribute(string url)
    {
        Url = url;
    }

    public PageAttribute()
    {

    }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Url is a required property and has to be provided")]
    public string Url { get; set; }
}

Control attribute:

Control attributes are used to provide information related to the ui controls on the page, like the id of the control, class, jquery selectors etc.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class ControlAttribute : Attribute
{
    public string Id { get; set; }

    public string Class { get; set; }

    public string Selector { get; set; }

    public PropertyExpressionOperator IdConditionOperator { get; set; }

    public PropertyExpressionOperator ClassConditionOperator { get; set; }
}

Other attributes

Similarly you can define other custom attributes like a SearchAttribute or a LazyLoad attribute that can be used to find controls based on custom data attributes or to denote that the controls are loaded at a later point of time etc.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class SelectorAttribute : Attribute
{
    public SelectorAttribute(string value)
    {
        Value = value;
    }

    [Required(AllowEmptyStrings = false, ErrorMessage = "Value is a required property")]
    public string Value { get; set; }
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class LazyLoadedAttribute : Attribute
{
       
}

Step 2: Creating the Jquery builder class

The JQueryBuilder class is responsible for building the jquery selector based on the properties defined on the control. For e.g the builder will combine multiple attributes like id, class, tag etc. to a valid jquery selector that can be later used to identify the control on the DOM.
A simple jquery builder can be created as
public class JqueryBuilder
{
    public string Selector { get; private set; }

    public void WithId(string id, PropertyExpressionOperator @operator = PropertyExpressionOperator.EqualTo)
    {
        if (String.IsNullOrEmpty(id))
        {
            return;
        }
        if (@operator == PropertyExpressionOperator.EqualTo)
        {
            Selector = String.Concat(Selector, "#", id);
        }
        else
        {
            SearchBy("id*", id);
        }
    }

    public void WithClass(string name, PropertyExpressionOperator @operator = PropertyExpressionOperator.EqualTo)
    {
        if (String.IsNullOrEmpty(name))
        {
            return;
        }
        if (@operator == PropertyExpressionOperator.EqualTo)
        {
            Selector = String.Concat(Selector, ".", name);
        }
        else
        {
            SearchBy("class*", name);
        }
    }

    public void WithSelector(string selector)
    {
        if (String.IsNullOrEmpty(selector))
        {
            return;
        }
        Selector = selector;
    }

    private void SearchBy(string name, string value)
    {
        Selector = String.Concat(Selector, "[", name, "=", value, "]");
    }      
}

Step 3: Extending the BrowserWindow object to use jquery selectors

Use the ExectuteScript method on the BrowserWindow its now easy to find controls on the page by injecting javascript into the page. In this example we’ll be using jquery to find controls on the page using selectors. But before that you should ensure that jquery is available on the page before using the selectors. The EnsureJqueryIsAvailable method will ensure that jquery is available on the page under test.
private static void EnsureJqueryIsAvailable(this BrowserWindow window)
{
    var needsJquery = (bool) window.ExecuteScript("return (typeof $ === 'undefined')");
    if (needsJquery)
    {
        window.ExecuteScript(@"
            var scheme =  window.location.protocol;
            if(scheme != 'https:')
                scheme = 'http:';
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = scheme + '//code.jquery.com/jquery-latest.min.js';
            document.getElementsByTagName('head')[0].appendChild(script);
        ");
    }
}
Next we’ll define two extension methods on the BrowserWindow to find controls using a jquery selector. The Generic find method is used to typecast the control to a generic control.
public static HtmlControl FindBySelector(this BrowserWindow window, string selector)
{
    window.EnsureJqueryIsAvailable();
    var uiControl = window.ExecuteScript(string.Format("return $('{0}')", selector));
    if (uiControl == null)
        return null;

    var hasMultipleResults = uiControl.GetType() == typeof (List<object>);
    if (hasMultipleResults)
    {
        return ((List<object>) (uiControl)).First() as HtmlControl;
    }
    return uiControl as HtmlControl;
}

public static T FindBySelector(this BrowserWindow window, string selector) where T : HtmlControl, new()
{
    window.EnsureJqueryIsAvailable();
    var control = new T {Container = window};
    var tag = control.TagName;
    if (!selector.ToUpper().StartsWith(tag.ToUpper()))
    {
        selector = String.Concat(tag, selector);
    }

    var uiControl = window.ExecuteScript(string.Format("return $('{0}')", selector));
    if (uiControl == null)
        return null;

    var hasMultipleResults = uiControl.GetType() == typeof (List<object>);
    if (hasMultipleResults)
    {
        var collection = (List<object>) uiControl;
        if (collection.Any())
        {
            return collection.First() as T;
        }
    }   
    return uiControl as T;
}

Step 4 : Creating the base page object

The base page object will implement the methods to load a page, parse the attributes and load controls on the page that can be later used to perform tests. The base page object defines the static creation method Create, that is responsible for creating a new instance of the page object and populating the properties with controls on the DOM.
public static TPage Create() where TPage : HtmlPage, new()
{
    var page = new TPage();
    var url = LoadAttributePageAttribute>().Url;
    page.Open(url);
    page.InitializeControls();
    return page;
}
The Open method launches a new browser window based on the url property on the page. The initialiaze controls methods is responsible for control finding and populating the page with the controls on DOM.
The complete base page looks like.
public class HtmlPage
{
    internal BrowserWindow Window { get; private set; }
    public void Open(string url)
    {
        var uri = new Uri(url);
        InitilizePlayback();
        Window = BrowserWindow.Launch(uri);
        Window.Maximized = true;
    }

    internal HtmlControl Find(string selector)
    {
        return Window.FindBySelector(selector);
    }

    internal T Find(string selector) where T : HtmlControl, new()
    {
        return Window.FindBySelector(selector);
    }

    private void InitilizePlayback()
    {
        if (!Playback.IsInitialized)
        {
            Playback.Initialize();
        }
        if (!Playback.IsSessionStarted)
        {
            Playback.StartSession();
        }
        SetSearchSettings(Playback.PlaybackSettings);
        Playback.PlaybackSettings.ContinueOnError = true;
        Playback.PlaybackError += (sender, args) =>
        {
            if (args.Result == PlaybackErrorOptions.Skip) return;
            if (Window != null)
            {
                Window.Close();
            }
        };
    }

    static void SetSearchSettings(PlaybackSettings settings)
    {
        settings.SearchInMinimizedWindows = true;
        settings.SearchTimeout = 10000; //10 seconds
        settings.ShouldSearchFailFast = true;
        settings.WaitForReadyLevel = WaitForReadyLevel.UIThreadOnly;
        settings.WaitForReadyTimeout = 5000;
    }

    internal void InitializeControls(bool lazyLoaded = false)
    {
        var map = new PropertyInfoToControlMap();

        //Find all properties on page with the control attribute
        var controlProperties = GetType().GetProperties()
            .Where(prop => prop.IsDefined(typeof(ControlAttribute), false)).ToList();

        var controls = map.From(controlProperties).Where(c => c.IsLazyLoaded == lazyLoaded);
        foreach (var control in controls)
        {
            var property = controlProperties.FirstOrDefault(c => c.Name == control.Name);
            MethodInfo findMethodInfo;
            if (property.PropertyType != typeof (HtmlControl))
            {
                findMethodInfo =
                    typeof (HtmlPage).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
                        .First(m => m.Name == "Find" && m.IsGenericMethod);
                findMethodInfo = findMethodInfo.MakeGenericMethod(property.PropertyType);
            }
            else
            {
                findMethodInfo =
                    typeof(HtmlPage).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
                        .First(m => m.Name == "Find");
            }
               
            var htmlControl = findMethodInfo.Invoke(this, new object[] { control.Selector });
            if (htmlControl == null && !control.IsLazyLoaded)
                throw new ArgumentException(String.Format("Page control {0} does not exist", control.Name));
            if (!htmlControl.GetType().IsAssignableFrom(property.PropertyType)) continue;
            property.SetValue(this, htmlControl);
        }
    }

    public void Refresh()
    {
        InitializeControls(true);
    }

    public static TPage Create() where TPage : HtmlPage, new()
    {
        var page = new TPage();
        var url = LoadAttributePageAttribute>().Url;
        page.Open(url);
        page.InitializeControls();
        return page;
    }

    private static T LoadAttribute()
        where TPage : HtmlPage
        where T : Attribute
    {
        var attribute = Attribute.GetCustomAttribute(typeof(TPage), typeof(T));           
        return attribute as T;
    }
}

Step 5: Translating the attributes to a control object.

The PropertyInfoToControlMap  object is responsible to create a control object with the selector property by parsing the attributes and building a selector using the JqueryBuilder class.
internal class Control
{
    public Control(string name)
    {
        Name = name;
    }

    public string Name { get; set; }
    public string Selector { get; set; }
    public bool IsLazyLoaded { get; set; }
}
internal class PropertyInfoToControlMap : IMap<Control, PropertyInfo>
{
    public IList<Control> From(IList<PropertyInfo> source)
    {
        return source.Select(ToControl).ToList();
    }

    private Control ToControl(PropertyInfo property)
    {
        var control = new Control(property.Name);
        var controlAttribute = property.GetCustomAttribute<ControlAttribute>(false);
        var builder = new JqueryBuilder();
        builder.WithId(controlAttribute.Id);
        builder.WithClass(controlAttribute.Class);
       
        var selectorAttribute = property.GetCustomAttribute<SelectorAttribute>(false);
        if (selectorAttribute != null)
        {
            builder.WithSelector(selectorAttribute.Value);
        }
        control.Selector = builder.Selector;
        control.IsLazyLoaded = property.GetCustomAttribute<LazyLoadedAttribute>(false) != null;
        return control;
    }
}

Step 6: Creating your page object.

Now you are ready to create your page objects using the objects created in the previous steps. Let’s see how a sample page object looks like
[Page(Url = "http://www.blogsprajeesh.blogspot.com/")]
public class BloggerPage : HtmlPage
{
    [Control]
    [Selector("h1 .title")]
    public HtmlControl Title { get; set; }

    [Control(Id = "Image2_img")]
    public HtmlImage ProfilePicture { get; set;  }
       
    public void EnsureTitleOnPage()
    {
        Assert.IsNotNull(Title);
    }

    public LinkedInPage NavigateToLinkedInPage()
    {
        Mouse.Click(ProfilePicture);
        Refresh();
        return new LinkedInPage();
    }

    public BloggerPage EnsureProfilePictureOnPage()
    {
        Assert.IsNotNull(ProfilePicture);
        return this;
    }
}

Step 7: Creating the tests

Using the page objects created, you can now write the tests like.
[CodedUITest]
public class BloggerPageTests
{
    [TestMethod]
    public void BlogHome_ShouldHaveATitleOnPage()
    {
        HtmlPage.Create<BloggerPage>()
            .EnsureTitleOnPage();
    }

    [TestMethod]
    public void BlogProfile_ShouldTakeToLinkedInPage()
    {
        HtmlPage.Create<BloggerPage>()
            .EnsureProfilePictureOnPage()
            .NavigateToLinkedInPage();
    }
}