Monday, April 8, 2013

Testing CSS in Plone with Robot Framework

[update 09-04: Modified as per Asko's comment]

You can use RF to make sure your CSS rules work as you want them to. This will give you confidence to move around large parts of you CSS codebase and be certain that everything still works. To do so, you must define your own library. 

Defining a custom library

In your robot test file, link the library like so:
Library  der.freitag.tests.robot.libraries.FreitagRobotSelenium2Keywords
The class FreitagRobotSelenium2Keywords in tests/robot/libraries.py holds the relevant methods to use Selenium: 
# -*- coding: utf-8 -*-
from robot.libraries.BuiltIn import BuiltIn

from selenium.webdriver.support.color import Color


class FreitagRobotSelenium2Keywords(object):

    @property
    def s2l(self):
        return BuiltIn().get_library_instance('Selenium2Library')

    def value_of_css_property(self, property_name, locator):
        """Returns value of property found by locator
        """
        s2l = self.s2l
        element = s2l._element_find(locator, True, True)
        prop_value = element.value_of_css_property(property_name)
        s2l._info('value of css property {0} : {1}'.format(property_name,
                                                           prop_value))
        return prop_value

    def _color_checker(self, color_value, locator, property):
        color_value = color_value.lower().replace('hex', '', 3)
        color_expected = Color.from_string(color_value).rgba
        color_found = self.value_of_css_property(property, locator)
        if color_expected != color_found:
            error_msg = 'Expected color {0}, found {1} instead.'
            raise AssertionError(error_msg.format(color_expected, color_found))

    def check_color(self, color_value, locator, property='color'):
        """Checks if element found by locator has correct value
        """
        self._color_checker(color_value, locator, property)

The methods to get and check the color were taken from https://github.com/bettertest-org/RobotSelenium2Keywords.

Using the library

The rest of our robot_colors.txt looks like this:
...
*** Variables ***

${X_AUTHOR_NAMES} =  //article//span[@class]


*** Test cases ***

Scenario: Author names are pink by default, no hover needed
  Given i am on the homepage
   Then author names are shown in pink


*** Keywords ***

Suite Setup
    Open browser  ${PLONE_URL}  browser=${BROWSER}  remote_url=${REMOTE_URL}  desired_capabilities=${DESIRED_CAPABILITIES}

Suite Teardown
    Close all browsers

Given i am on the homepage
    Location should be  ${PLONE_URL}

Then author names are shown in pink
    Check color  \#bd014d  ${X_AUTHOR_NAMES}


More info

Check out plone.app.robotframework.

2 comments:

Asko Soukka said...

Hi Kees! Great that you are still sharing your experience.

It's nice to see that you've digged into using Remote Libraries with Plone, but actually it's too complex solution for this. You need to use Remote Libraries with Plone only, when you need access to Plone database - e.g. you'd like to create content to test later with browser. Also, it's not safe to make Selenium-calls from remote libraries (they work now only, because both Selenium and Plone are run in the same process thanks to the use of zope.testrunner).

What you could do instead, is to implement a simple Python class with your keywords (the same as in your remote library, but without remote library boilerplate methods) and import it with "Library der.freitag.tests.libraries.FreitagRobotSelenium2Keywords".

Finally, I've now released former plone.act with the final name plone.app.robotframework and there's a tutorial about it at http://developer.plone.org/reference_manuals/external/plone.app.robotframework/happy.html

Kees Hink said...

Thanks! Will update this post ASAP.