PloneSelenium
Functional Testing for Plone


Maik Röder

Ingeniweb

<maik.roeder@ingeniweb.com>

PloneSelenium is a Plone Product making it easy to create functional tests for Plone. Content management projects usually involve making changes to the default Plone behaviour, installing third-party products and developping custom content types. PloneSelenium comes with a standard library of functional tests making sure Plone remains stable while you adapt it to your needs. PloneSelenium can be extended with custom functional tests, supporting test-driven development allowing you to deliver features to your customer incrementally. PloneSelenium improves your productivity and assures the quality of your Plone-based sites.


Plone development can take different forms. A simple change may consist in overriding a script, or making a change to an existing Plone Page Template. You may have to change some permissions or actions, which are used in several different contexts. In some projects, you'll need to add a custom content type, which comes with a different workflow. You'll also install some products and integrate them into your site. In all of these cases, PloneSelenium can ba a very useful tool.


With PloneSelenium you can create functional tests inside Plone, and test them directly on your application through the web. You can see the functional tests running your application in the browser, step through the steps of the test suite, and verify the behaviour of your application while it is running. At any point you can stop the test and rerun it, maybe after having made some change to your application code. At the heart of PloneSelenium is the Selenium engine, which is a set of templates and scripts making it possible to run tests directly in the browser using JavaScript. (http://selenium.thoughtworks.com/index.html).


OVERVIEW

PloneSelenium is based on the idea that it should be as natural as possible for a Python programmer to write Selenium tests. In basic Selenium you have to write HTML files with tables containing the test, which is not very appealing to the Python programmer. On the other hand, functional tests can also be written in Python like unit tests that drive the brower, but you are actually loosing the interactivity of the PloneSelenium developpment mode. PloneSelenium tests are written in a simple Python Script. You have the choice between developping your tests through the web or on the file system in the skin layer of a product.

## Script (Python) "get_example_ftests" ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters= ##title= ## selenium = context.portal_selenium suite = selenium.getSuite() suite.addTests("Test Anonyous user access", "Go to the Plone site", suite.open('/'), "Go to the news page", suite.open('/news'), ) return suite

This is a Python Script get_example_ftests.py, defining a functional test suite called "Test Anonyous user access" with two tests, "Go to the Plone site" and "Go to the news page". Once it is registered as a functional test in PloneSelenium, you can run the test, and it will first open the Plone site, and then go to the news page.


In this simple example nothing is really tested, we are just navigating the Plone site. The following code shows a more useful test, including some verifications.


## Script (Python) "get_usecase_login_ftests" ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters= ##title=Use case "Login" selenium = context.portal_selenium suite = selenium.getSuite() selenium.addUser(id='samplemember', fullname='Sample Member', roles=['Member',]) suite.addTests("Test Plone login", "Login as member", suite.open("/logout") suite.verifyElementPresent('portlet-login'), suite.verifyElementPresent('__ac_name'), suite.verifyElementPresent('__ac_password'), suite.type("__ac_name", 'samplemember'), suite.type("__ac_password", "admin"), suite.clickAndWait("submit") suite.verifyTextPresent("You are now logged in"), suite.verifyElementNotPresent("portlet-login"), ) return suite


In the login use case, we are preparing the functional test beforehand by adding a new user called "samplemember" with the role "Member". The login test first makes sure that an currently logged in user is logged out. Then we verify that there exists an HTML element with the id "portlet-login", which is the id of the portlet in which the login takes place. Next, we verify that two further elements necessary for login are existing, one for entering the name, and the other for the password. Next, we are typing the name and password of the user and click on the submit button. It is verified that the "You are now logged in" test is shown on the page, and that the login portlet is no more shown.


PloneSelenium takes care of adding users and groups for you. It also contains some useful tests in a common library for adding the basic content types and for logging in and logging out. PloneSelenium features a wide range of functional tests from which you can take inspiration. Tests are available for the Plone workflow, permissions, content types and all kinds of use cases.


Conclusion


PloneSelenium eases the development of functional tests in Plone. It gives you the possibility to write light-weight tests in Python, and let's you run them interactively through the web. It has been used successfully in several large applications, and is featured in a growing number of products. The goal of PloneSelenium is to be included in Plone, and to become the standard way of developping functional tests in Plone. It is already possible to export PloneSelenium tests to be run as static tests in Zelenium, and it will soon be possible to export them into a unit testing framework for functional testing in a continuous integration setting.


AVAILABILITY


PloneSelenium is available as a released package in the Ingeniweb project area on Sourceforge.