Zope 3 Functional Testing

 How to run Zope 3 functional tests

  In the top-level directory, run "python test.py -f".  If you've read
  UNITTEST.txt you'll notice that the same script is used, but with an
  additional argument '-f'.  That's because in Zope 3 functional tests are
  just a special case of unit tests.  The rest of test.py options work as
  well, for example you can use "python test.py -fpv" to get a nice progress
  indicator.  For information about all options run "python test.py -h".

  If your Zope 3 doesn't yet have a products.zcml, create one by
  copying products.zcml.in to products.zcml.

 Zope Functional Testing

  Functional tests live in directories called "ftests" all over the source
  tree.  They use the same PyUnit framework as unit tests, and I recommend
  reading UNITTEST.txt and familiarizing with unit tests before moving on to
  functional tests.

  Functional tests differ from unit tests in that nearly all ZCML configuration
  files are parsed and a virtual in-memory storage is created before running
  them.  Any changes made to the storage will be discarded at the end of the
  test.

 What Functional Tests Are

  Functional tests are meant to test more than just a single unit of code.
  While unit tests make sure that all components work as designed, functional
  tests ensure that those components are connected correctly, and that the
  system works as a whole.

 Writing Functional Tests

  Functional tests in Zope 3 use the same conventions as unit tests, but with
  the following differences:

   - Functional test modules live in directories called 'ftests'.

   - Functional test cases inherit from
     zope.testing.functional.FunctionalTestCase or
     zope.testing.functional.BrowserTestCase instead of unittest.TestCase.

   - All global services, components etc. defined in assorted configure.zcml
     are available during test run time.

   - A volatile in-memory storage with an empty root folder and all essential
     services is available and is automatically cleaned after every test.
     The test code can access and modify the root folder by calling
     self.getRootFolder().

   - Browser requests can be emulated by inheriting from BrowserTestCase and
     calling self.publish().  See the docstring in
     src/zope/app/tests/functional.py for detailed information.  Here are a
     couple of simple examples::

        response = self.publish('/folder/object')
        self.assertEquals(response.getStatus(), 200)
        self.assert_(response.getBody().find("some text") != -1)

        response = self.publish(
            '/something/action.html',
            basic='username:password',
            form={'id': u'foo', 'UPDATE_SUBMIT': u'Submit'})
        self.assertEquals(response.getStatus(), 302)
        self.assertEquals(response.getHeader('Location'),
                          'http://localhost/something.html')

   - If you want to make changes made directly through access to
     self.getRootFolder() available to an emulated request, make sure to commit
     the transaction.  Here's how you do it::

       import transaction
       transaction.commit()

   - Functional tests should not change any global registries.  In particular,
     functional unit test cases should not inherit from
     zope.testing.cleanup.CleanUp or any of the PlacelessSetup classes that
     inherit from CleanUp.

