Tuesday, 29 November 2011

Highlighting elements in a Webdriver automated test

So, you use Selenium 2's Webdriver to automate some unit tests in your C# .NET enterprise web application? Me too.  Our list of tests is growing longer and longer, and watching web pages fly by automatically can be amusing - but which element is being looked for, or clicked?  Can you highlight the element before Webdriver clicks on it?



Unfortunately a Webdriver IWebElement has a GetAttribute() but not a SetAttribute().  Visual C# Kicks shows us how to extend IWebElement with a SetAttribute method:

public static void SetAttribute(this IWebElement element, string attributeName, string value)
{
    IWrapsDriver wrappedElement = element as IWrapsDriver;
    if (wrappedElement == null)
        throw new ArgumentException("element", "Element must wrap a web driver");

    IWebDriver driver = wrappedElement.WrappedDriver;
    IJavaScriptExecutor javascript = driver as IJavaScriptExecutor;
    if (javascript == null)
        throw new ArgumentException("element", "Element must wrap a web driver that supports javascript execution");

    javascript.ExecuteScript("arguments[0].setAttribute(arguments[1], arguments[2])", element, attributeName, value);
}

But how do you turn that into a highlight?

First, a couple of Click() methods in your base test class:

public void Click(string elementId)
{
    Click(By.Id(elementId));
}
public void Click(By by)
{
    IWebElement element = _driver.FindElement(by);
    element.Highlight();
    element.Click();
}

so we can click on elements a little more simply:
Click("some_id");
instead of
Driver.FindElement(By.Id("some_id")).Click();
and
Click(By.CssSelector("#mainContentContainer_someIdString > span"));
instead of
Driver.FindElement(By.CssSelector("#mainContentContainer_someIdString > span")).Click();

Now in my Click() method you can see element.Highlight(); which is an extention in addition to the SetAttribute() above:

public static void Highlight(this IWebElement element)
{
    const int wait = 150;
    string orig = element.GetAttribute("style");
    SetAttribute(element, "style", "color: yellow; border: 10px solid yellow; background-color: black;");
    Thread.Sleep(wait);
    SetAttribute(element, "style", "color: black; border: 10px solid black; background-color: yellow;");
    Thread.Sleep(wait);
    SetAttribute(element, "style", "color: yellow; border: 10px solid yellow; background-color: black;");
    Thread.Sleep(wait);
    SetAttribute(element, "style", "color: black; border: 10px solid black; background-color: yellow;");
    Thread.Sleep(wait);
    SetAttribute(element, "style", orig);
}

I've just used some plain garish black and yellow so I can spot the change quickly as the tests fly by!  Now each element will flash a few times as it is "clicked" by the web test!

4 comments:

Max Russell said...

How did you organise this - did you have it all in the same class and namespace as the test, or in a helper of some kind?

thanks

Max Russell said...

How did you organise this in code - did you have this all in the same class and namespace, or a separate helper class or something?

Seems pretty mad that a highlight element method isn't a default in Selenium.

Iain said...

Hi Max,

I have a base test class that all my Selenium tests inherit from. In there I set up the common selenium stuff (creating the webdriver etc) and have some functions like Click(), which call the highlight code.

It's really eye candy, so I'm not surprised it's not included in Selenium, but it did help me sometimes when I had programmed the click on the wrong element.

Stu said...

I tried adding this to a project which uses the the page object framework in OpenQA.Selenium.Support.PageObjects library.

Unfortunately the SetAttribute method fails on "page object" elements (of type WebElementProxy) as the conversion to IWrapsDriver returns null.

I am stuck trying to figure out how to get IWrapsDriver out of a WebElementProxy "page object" element, if you had any thoughts on how this can be done it would be much appreciated.

 
Copyright 2009 Another Blog. Powered by Blogger Blogger Templates create by Deluxe Templates. WP by Masterplan