metaprogramming and politics

Decentralize. Take the red pill.

New Plugin architecture and plugins for py.test

with one comment

I just merged the plugin branch and am very happy about it. Part of the effort was driven by moving core functionality to become a plugin: Terminal reporting is now fully a plugin, contained in a single file including tests. It does it work solely by looking at testing events. Plugins can also add new aspects to tests files – for example the plugin adds ReST syntax, referential integrity and URL checking for Text files. (I used it for checking my blog post and its links, btw).

Pytest’s good old files are still useful: you can define project or directory specific settings, including which plugins to use. For now, many old extensions should work unmodified, as exemplified by PyPy‘s extensive files. It’s easy to port a conftest file to a plugin. In fact, you can first define a local "ConftestPlugin" and later move it to become a cross-project one – a matter of renaming the file and the class, done!

To serve as guiding examples, I drafted some initial plugins and implemented neccessary hooks within py.test core.

If you wan’t to get a feel on how plugins are implemented, here is the plugin which adds a command line option to allow logging of all testing events. It’s instructive to look at how it’s done as well as the output because it shows which testing events are generated.

class EventlogPlugin:
    """ log pytest events to a file. """

    def pytest_addoption(self, parser):
        parser.addoption("--eventlog", dest="eventlog",
            help="write all pytest events to the given file.")

    def pytest_configure(self, config):
        eventlog = config.getvalue('eventlog')
        if eventlog:
            self.eventlogfile = open(eventlog).open('w')

    def pytest_unconfigure(self, config):
        if hasattr(self, 'eventlogfile'):
            del self.eventlogfile

    def pyevent(self, eventname, *args, **kwargs):
        if hasattr(self, 'eventlogfile'):
            print >>self.eventlogfile, eventname, args, kwargs

This plugin code is complete, except that the original file contains tests. The eventlog plugin methods above are called in the following way:

  • def pytest_addoption(self, parser) is called before
    commandline arguments are parsed.
  • def pytest_configure(self, config) is called after parsing
    arguments and before any reporting, collection or running
    of tests takes place.
  • def pytest_event(self, eventname, *args, **kwargs) is called
    for each testing event. Events have names and come with
    arguments which are supplied by the event producing site.
  • def pytest_unconfigure(self, config) is called after
    all test items have been processed.

If you want to start writing your own plugin, please use an svn checkout of:

and activate it by e.g. python develop.

If you want to write a plugin named pytest_XYZ, you can tell pytest to use it by setting the environment variable PYTEST_PLUGINS=XYZ or by putting pytest_plugins = 'xyz' into a test module or file.

A good way to contribute is to copy an existing plugin file to your home dir and put it somewhere into your PYTHONPATH. py.test will use your version instead of the default one and you can play with it untill you are happy (and see to also add some tests showing the new behaviour).

If you have questions or problems, you are invited to post here or to the py-dev mailing list. I’d definitely like to pluginize more of pytest and add hooks as needed and am happy for feedback and suggestions before i freeze the API for 1.0.


Written by holger krekel

February 27, 2009 at 11:22 am

One Response

Subscribe to comments with RSS.

  1. […] 23rd June 2009 Nice tip for making your CSS more performant.How to write plugins for py.test. I found this invaluable as I wasn’t able to decipher how to … css linkeyes performance py.test Python […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: