Monday, August 24, 2015

Do you use CodedUI for testing responsive webdesign?

Responsive web design has been around for quite some time. Most of the websites created nowadays are built with responsiveness as a main design consideration. But still automating responsive website testing is not adopted in software teams very well. Marcel has a nice post on how to resize the browser window to test responsive websites.

In this post, I’ll try to combine his solution with attributes to specify the view port details and then use this information to test responsive websites.


Use extensions methods to resize Window


public static class BrowserWindowExtensions
{
    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hwndInsertAfter, int x, int y, int cx, int cy, uint uFlags);

    public static void ResizeWindow(this BrowserWindow control, int width, int height)
    {
        SetWindowPos(control.WindowHandle, (IntPtr)(-1), 0, 0, width, height, 0x0002 | 0x0040);
    }
}

Use attributes to specify ViewPort


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class BrowserViewPortAttribute : Attribute
{
    public BrowserViewPortAttribute(int width, int height)
    {
        Width = width;
        Height = height;
    }

    public int Width { get; private set; }
    public int Height { get; private set; }
}

The BrowserViewPort attribute can be now used in the CodedUI test class or test methods to define the ViewPort.

[TestMethod]
[TestCategory("Lumia 930")]
[BrowserViewPort(320, 525)]
public void Google_ViewPortSample()
{
    PageFactory
        .Create<GooglePage, GoogleMap, GoogleValidator>("http://www.google.com", TestContext)
        .LookFor("nuget")
        .Search()
        .ValidateNugetResultsLastItemAs1("Hosting Your Own NuGet Feeds");
}

Extend the TestContext to expose ViewPort information


public static class TestContextExtensions
{

    public static BrowserViewPortAttribute GetViewPort(this TestContext context)
    {
        var testClassType = Assembly.GetExecutingAssembly().GetType(context.FullyQualifiedTestClassName);
        var classViewPort = testClassType.GetCustomAttribute<BrowserViewPortAttribute>();
        var testMethodInfo = testClassType.GetMethod(context.TestName);
        if (testMethodInfo == null)
        {
            return classViewPort;
        }
        var methodViewPort = testMethodInfo.GetCustomAttribute<BrowserViewPortAttribute>();
        return methodViewPort ?? classViewPort;
    }
}

Use these in the page factory to create PageObjects


private static TPage CreatePage(string url, TestContext context, bool disposeOnPlayback = true) where TPage : BasePage
    where TMap : BaseMap where TValidator : BaseValidator
{
    var window = BrowserWindow.Launch(new Uri(url));
    if (context != null && context.GetViewPort() != null)
    {
        var viewPort = context.GetViewPort();
        window.ResizeWindow(viewPort.Width, viewPort.Height);
    }
    else
    {
        window.Maximized = true;
    }
    if (!disposeOnPlayback)
    {
        window.CloseOnPlaybackCleanup = false;
    }
    var map = Activator.CreateInstance(typeof (TMap), window) as TMap;
    var validator = Activator.CreateInstance();
    var page = Activator.CreateInstance();
    validator.Map = map;
    page.Map = map;
    page.Validator = validator;
    return page;
}


No comments: