[Zope3-dev] RFC: Tutorial Generator

Stephan Richter srichter at cosmos.phy.tufts.edu
Mon Nov 7 09:19:47 EST 2005


Hi everyone,

now that we have testbrowser, there is a totally new range of possibilities. 
One opportunity I would like to investigate is the ability to generate 
moview-like and/or interactive tutorials based on testbrowser doctests.  I 
have written up some thoughts and I would greatly appreciate it, if you could 
comment. Here you go.

Thanks,
Stephan

--------------------------------------------------------------------------------------------------------
===================
Generated Tutorials
===================

We have recently started to write our functional doctests using the
``zope.testbrowser`` package. The advantage of using the testbrowser is, of
course, that we are describing the real interaction of the user with the
browser. This does not only provide much nicer documentation, but also
provides us with additional information about the usage of the Web
application.

Let's imagine we could use those documentation files to create fully generated
tutorials. The best about this is that I believe it is possible! This document
is meant to outline possible technical approaches to implement this tutorial
generator.

So far I have identified three desirable use cases:

(1) Generate a Flash movie that runs through the tutorial. The flash movie is
    generated offline and then is simply distributed as a static Web page/SWF
    file.

(2) Provide a live demonstration, which can be started using a simple command,
    like this::

      [Z3]$ showTutorial.py 
src/zope/app/authentication/browser/groupfolder.txt

    When this script is called, Zope 3 and a browser should be started, and
    the tutorial should start running.

(3) Provide a hands-on tutorial, where we ask the user to enter all the
    input. This could be started using a similar command to the one above::

      [Z3]$ doTutorial.py src/zope/app/authentication/browser/groupfolder.txt

The exciting part about this is that the same technical solutions could easily
be used to fulfill all three use cases. In the sections below I am going to
outline some of the technical aspects that need to be solved and suggest
solutions based on some initial research I conducted.


Reading and Evaluating the Doctest File
---------------------------------------

The code in the ``doctest`` module is quiete modular; at least it should be no
problem to parse the doctest into its documentation and example parts:

  >>> import doctest
  >>> text = open('./zope/testbrowser/README.txt', 'r').read()
  >>> parser = doctest.DocTestParser()
  >>> result = parser.parse(text)
  >>> print result[0]
  ================
  The Test Browser
  ================

  The ``zope.testbrowser`` module exposes a ``Browser`` class that
  simulates a web browser similar to Mozilla Firefox or IE.

  >>> result[1]
  <doctest.Example instance at 0xb7a2d5cc>
  >>> print result[1].source
  from zope.testbrowser import Browser

  >>> print result[1].want

Running the examples is a little bit more tricky, since the execution code is
designed only to work with a `DocTest` instance. However, I believe by writing
a common `DocTest` class, we can have better control over the runtime of the
examples; on the other hand, we might just be able to recode it.


Pushing Examples to the Browser
-------------------------------

Once we have collected the examples, they are executed using a custom
testbrowser class. The implementation of the custom testbrowser is probably
the most tricky part of the entire solution stack, because it is the piece
that communicates with the browser.

What we really want to be able to do is to push the next action to the
browser, and the browser uses some JavaScript to execute the action. On the
other hand, we want to pull information from the browser, such as the document
source, so that the comparison examples do not fail and provide the tutorial
controller with feedback about the current browser state.

Here are some approaches that could be taken:

(1) The only non-hacky solution, in my opinion, is to interact with the
    browser on the desktop and not the Web-level. For example, using KDE, we
    could utilize DCOP that allows us enough control over Konqueror to
    effectively do all necessary manipulations. Here is a small CLI session
    that I did::

      $ dcopstart konqueror
      konqueror-1000

      $ dcop konqueror-1000 | grep "html-widget"
      html-widget1

      $ dcop konqueror-1000 konqueror-mainwindow#1 openURL 
"http://localhost:7080/"

      $ dcop konqueror-1000 html-widget2 evalJS 
"tags=document.getElementsByTagName('a'); for (i=0;i<=tags.length;i++){if 
(tags[i].text.indexOf('Persons') != -1) alert(tags[i].text);}"

    The advantages of this solution are as obvious as the disadvantages. One
    of the big plusses is that we have full control over the browser process,
    even on a desktop level. Some of the disadvantages include the disability
    to run over the network and being KDE specific.

(2) The second approach basically uses the classical Web pull model. The
    actions are then evaluated using some JavaScript. We could probably reuse
    some of the Selenium code or JSON to execute the actions.

    I think there are two viable approaches for the pull:

    (a) Have a hidden frame that checks perodically for new actions.

    (b) Use a long-running stream. Uwe Oestermeier has done some prototyping
        in this area using twisted. You basically keep a stream open and push
        information through the stream as the data is available.

    The disadvantage of this approach is that it is a pretty complex
    solution. The advantage is that pretty much any browser that supports the
    `XmlHttpConnection` class will work with this solution and it can be done
    over the network.

I am still not clear on many of the technical details, especially since I do
not know JavaScript very well. Any comments and suggestions are very welcome.


Communicating the Documentation Text
------------------------------------

The demonstration would be pretty useless without providing the user with the
documentation text one way or another. There are two approaches that can be
taken:

(1) Display the text in a floating div or separate frame. This should be
    fairly easy in comparison to the callenges above.

(2) Use a free TTS tool. I have installed festival 1.95 (1.43 did not work for
    me) and it works like a charm. This would only work on local installations
    of course.

I don't think this part should pose any difficulties, whatever route we take.


The Final Output
----------------

When recording an SWF file, some more processing must occur. Benji pointed me
yesterday to `vnc2swf`. The new version is based on Python and is called
`pyvnc2swf`. It supports both, screen capturing and sound recording. I think
it should be pretty straight forward to setup the software to record the
sessions properly.


More information about the Zope3-dev mailing list