Skip to content

Commit

Permalink
add text documenting pluggable event handlers, bug 583936
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Hammel committed Oct 21, 2010
1 parent 7eedd5e commit b8680d8
Showing 1 changed file with 143 additions and 0 deletions.
143 changes: 143 additions & 0 deletions mozmill/pluggable_events_handlers.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
Pluggable Events
================

With the addition of pluggable events, mozmill has mostly become a
python event dispatcher system. Mozmill is run like

mozmill -app firefox -t path/to/test.js [options]

This will do the following:

- the application, in this case 'firefox', will be looked for [see:
mozrunner.runner]

- a profile object will be created of the approriate type [see:
mozprofile.profile]

- a python-javascript bridge will be created [see: jsbridge]

- the ``test.js`` file will be sent over the jsbridge where it is
loaded and executed [see: resource://mozmill/modules/frame.js]

- events will be sent from JavaScript back to python where they will
be listened for [see: mozmill:MozMill and
resource://mozmill/modules/frame.js]

Note that except a few conventions, mozmill is more driver code and
event handling than a testing framework.


Events
------

Events send the signature ``(eventType, obj)``. ``eventType`` is
the string name of the event (e.g. 'mozmill.endTest') and ``obj`` is
the "test" object. A python callable signature for a given event
takes ``obj`` as an argument, e.g:

self.add_listener(self.persist_listener, eventType="mozmill.persist")
def persist_listener(self, obj):
self.persisted = obj


Pluggable Event Listeners
-------------------------

MozMill allows python modules to plug into the event listener system.
This is done by denoting them as a setuptools entry point with the key
``mozmill.event_handlers`` (see mozmill's setup.py for examples).

[TODO: add support for allowing handlers to live in free-standing
files and possibly on a python dotted path.]

Currently, when invoking mozmill through the command line, all
setuptools entry points with the ``mozmill.event_handlers`` are
called.

[TODO: add a ``--disable=`` flag to the command line which will
disable plugins]

MozMill has two built-in listener plugins:

- a logger (``mozmill.logger:LoggerListener``)
- a JSON reporting module (``mozmill.report:Report``)

You can see how these are instantiated in mozmill's setup.py in the
``entry_points`` section.

[TODO: the existing LoggerListener and Report classes are straight
ports of the previous functionality. They should both be cleaned up
and restructured towards the end of making them more robust and extensible]


Command Line Invocation Infrastructure
--------------------------------------

Event handlers may add events via an ``add_options`` class method to
which the parser is passed [see: mozmill.CLI.add_options].
When driving via the command line, the handlers are instantiated with
the passed-in options. ``mozmill.handlers.instantiate_handler``
introspects the passed in handler to determine which command line
options are needed and constructs the object based on this
information (it is a handler-factory). If the handler raises a
``mozmill.handlers.HandlerMatchException`` the handler is not
instantiated or passed to the MozMill constructor.

As an example, see the constructor of ``mozmill.report.Report``. If
``report`` is None, as it would be if not specified via the command
line (see the class's ``add_options`` method for ``--report``), then
the class is not instantiated or utilized.


Structure of an Event Handler
-----------------------------

The basic methods for an event handler is given in
``mozmill.handlers.EventHandler``. While this class is never
inherited from, it shows the basic methods that event handlers can
have.

The ``add_options`` method is used to add options to the command line
parser.

In order to be utilized from the command line, the handler should have
a constructor. A blank one is fine. The attribute names for the
constructor signature should match those in ``add_options`` if you
wished them to be controllable from the command line.

If an event handler is callable, then all events and their event types
will be passed to the ``__call__`` method.

The event handler should have an ``events`` method. This should
return a dict of names of events to listen for mapped to the methods
that listen to these events.

[TODO: currently the event type is a string by convention only. We
have no catalog of events to be listened for. A list of applicable
events should be maintained as well as when each is called by the
tests. Bonus points to make this programmatic]

If the event handler has a ``stop()`` method, this is called at the
end of the test run internally to python (no JS communication is done
here). Whether the stop is fatal or not (something bad has happened,
e.g. an exception) is passed in. This gives event handlers the
opportunity to output final statistics and otherwise do cleanup.

[TODO: stop should be made a real event instead of being treated
specially]


API Usage
---------

One of the primary motiviations for the restructuring of the command
line handling as well as adding pluggable events is to make writing
APIs around MozMill easier. Previously, it was difficult (a
significant chunk of code needed to be replicated, which of course
relies on innards not changing to be maintainable) to invoke MozMill
programmatically at all and impossible to extend it in many ways.

[TODO: provide a sample API handler]

[TODO: provide an abstract factory that allows easier instantiation of
MozMill when not going through the command line]

0 comments on commit b8680d8

Please sign in to comment.