Saturday, 15 March 2014

Testing Radio button group with Arquillian Graphene


In the last blog post, I showed you how you can use the Arquillian Graphene Page fragments.  It allows you create reusable test components for screen elements.  You can encapsulate the required test functionality nicely which result in readable and maintainable test code.

But the @Root annotation can only be placed on a single WebElement, so how can you test the radio button input group?

Radio button group.

There are various occasions where you can select one option out of a list where each option is shown with a radio button in front of it.

Within the HTML code, you have various input elements with the same name. 

So how can you create a page fragment which point to the whole set of input fields? This allows to test the radio button styled input fields when you have for instance custom selection indications like angularPrime has.

Manual search

Since the @Root annotation cannot be placed on a Collection, like List, of WebElements, I came up with the following solution.

I created the RadioButtonGroup class which acts as a page fragment.  So it has one attribute which is marked as the @Root.  Since it is a normal Page fragment, I can use it in my test class as.

    @FindBy(name = "rd") 
    private PuiRadiobuttonGroup puiRadiobuttonDefault;

Although there are more then one element on the page that fulfil the selection criterium, only the first one is taken.  Well I’m not interested that it is the first one, as long as I get one of them without any exception being thrown.

So how do I get then the list of all radio button input elements that have the same name?
Each method in the page fragment checks if the list is already filled, if not, the following code is executed.

            List<WebElement> elements = driver.findElements("name"))); 
            buttons = new ArrayList<PuiRadiobutton>(); 
            for (WebElement element : elements) { 
                PuiRadiobutton radiobutton = new PuiRadiobutton(); 
                radiobutton.initializeManually(element, this); 

By using the driver, we can search for all elements with the same name and then instantiate an instance of the object which keep the reference to one of the radio button input fields.

The idea is that we mimic the Page fragment within the PuiRadiobutton class.  Setting the root element is quit easy, as we got a reference to it from the findElements on the driver instance.  But I need also the initialisation of the other attributes which are marked with @Drone and @FindBy to have a ‘real’ Page fragment.

In the Graphene code itself, I found the code which is responsible for injecting the references under normal circumstances.  I was able to use this to initialise my radio button instance.  The important part of my code is as follows:

            List<Field> fields = ReflectionHelper.getFieldsWithAnnotation(getClass(), FindBy.class); 
            for (Field field : fields) { 
                By by = FindByUtilities.getCorrectBy(field, How.ID_OR_NAME); 
                // WebElement 
                if (field.getType().isAssignableFrom(WebElement.class)) { 
                    WebElement element = root.findElement(by); 
                    setValue(field, this, element); 
                    // List<WebElement> 
                } else if (field.getType().isAssignableFrom(List.class) && getListType(field) 
                        .isAssignableFrom(WebElement.class)) { 
                    List<WebElement> elements = root.findElements(by); 
                    setValue(field, this, elements); 


With the above explained hack, I’m able to create a page widget which represents a group of elements which has no unique identifier in the DOM tree, like a radio button group.
Now i can easily write some test code like

        assertEquals(2, puiRadiobutton.getNumberOfButtons()); 
        assertEquals("2", puiRadiobutton.getSelectedValue());

It would be nice if the framework could foresee a solution for these kind of situations out of the box.

No comments:

Post a Comment