Browserless Development
Introduction
Testing the code in your product by accessing a Plone instance through a web browser is very inefficient and can get quite frustrating at times. You write a small piece of code, then reload it in your zope instance, maybe reinstall through portal_quickinstaller, then manual test the feature in your browser.
I have found that using the testing features of Python and Plone it is very easy to test your code without ever opening a browser. Read on and learn!
Testing Framework
Created by paster if using the archetype template. Many products in our svn have testing code in them (uwosh.themebase, Product.UWOshSuccess)
paster create -t archetype uwosh.example
Your product's testing code lives in the tests folder:
tests/ __init__.py base.py test_doctest.py
Running Tests
Testing method that comes with plone
To run all the tests in an egg use "-s egg.name":
Plone/zinstance/bin/instance test -s uwosh.example
To run a specific test module in an egg use "-s egg.name -t module.name":
Plone/zinstance/bin/instance test -s uwosh.example -t test_person
Starting in Plone 4 the testrunner does not come built in. In your buildout.cfg you will need to add test to parts and add a [test] section.
parts =
...
test
[test]
recipe = zc.recipe.testrunner
eggs =
${buildout:eggs}
uwosh.example[test]
To run a test you will then do something like:
Plone/zinstance/bin/test -s uwosh.example
Roadrunner
Roadrunner is much faster than the standard Plone method because after it creates Plone instance for testing it reuses it each time the tests are run. You will want to always use Roadrunner because of the time it will save you.
Installing Roadrunner requires adding a recipe to your buildout.cfg, where "packages-under-test" is a list of the eggs that you want to test with Roadrunner:
[roadrunner] recipe = roadrunner:plone packages-under-test = uwosh.example
Then just run your tests using the same options as "instance test":
Plone/zinstance/bin/roadrunner -s uwosh.example -t test_exampleperson
Different Tests
Types of tests
- Unit tests test one specific piece of functionality, for example one method or function
- Integration tests test that several pieces of functionality work together correctly
- Browser tests simulate a web browser interacting with Plone and allow you to test UI features
Styles of writing tests
- Doctests are made up of Python code mixed with documentation. They can be written as a separate text file such as a README.txt file or can be included in the docstrings of your Python code.
- Tests can also be written as regular Python code, which is often easier to debug, write, and read.
Tips and Tricks
pdb
pdb is the python debugger. Use it anywhere in your code to see what's going on. Anytime you want to stop the code and have a look around you should use pdb. You can start the debugger at any point by adding the following line of code to your product:
import pdb; pdb.set_trace()
Commands include: continue, up, next, list, skip, step, help
Useful python features for inspecting objects in pdb
dir() - Use this to see what attributes are available for any object.
>>> x = "asdf" >>> dir(x) ['__add__', '__class__',.........,'swapcase', 'title', 'translate', 'upper', 'zfill'
filter() - As dir() returns a long list of attributes it is often helpful to search through them:
>>> filter(lambda x: 'split' in x, dir(x)) ['rsplit', 'split', 'splitlines']
__doc__ - the __doc__ attribute is the docstring for an object if it has one:
>>> print x.__doc__ str(object) -> string Return a nice string representation of the object. If the argument is a string, the return value is the same object.
Write the tests first
Before implementing a feature, write a test for it, run the test and make sure it fails, add the feature, then victoriously watch the test pass. You will feel super great and potentially high five everyone in sight.
References
Best tutorial ever: http://plone.org/documentation/tutorial/testing
Roadrunner: http://pypi.python.org/pypi/roadrunner











