This is a series of tests for the behavior of the category factory class::

    >>> from contentratings.category import RatingsCategoryFactory
    >>> from contentratings.interfaces import IRatingStorage
    >>> from contentratings.tests.test_category import ITestRatingType

Now we should be able to instantiate a simple RatingsCategoryFactory,
and check the default values::

    >>> category = RatingsCategoryFactory(u'My Title')
    >>> category.title
    u'My Title'
    >>> category.__name__
    u''
    >>> category.view_name
    u'ratings_view'
    >>> category.description
    u''
    >>> category.order
    100
    >>> category.read_expr is None
    True
    >>> category.write_expr is None
    True
    >>> category.read is None
    True
    >>> category.write is None
    True
    >>> IRatingStorage.implementedBy(category.storage)
    True
    >>> ITestRatingType.implementedBy(category.storage)
    False

This is using the default storage (an IUserStorage implementation).
If we set a custom storage, that should be used::

    >>> from contentratings.tests.test_category import DummyStorage
    >>> category.storage = DummyStorage
    >>> ITestRatingType.implementedBy(category.storage)
    True

When we set the read/write validation expressions.  They are complied
and stored in attributes.  Empty values set the attributes to None::

    >>> category.read_expr = "python:context"
    >>> category.read
    <PythonExpr (context)>
    >>> category.write_expr = "python:userid"
    >>> category.write
    <PythonExpr (userid)>
    >>> category.read_expr = category.write_expr = None
    >>> category.read is None
    True
    >>> category.write is None
    True
    >>> category.read_expr = ''
    >>> category.read is None
    True

The factory is of course callable and returns an IRatingManager.  We
have no adapter initially though::

    >>> category(my_container) is None
    True

We can provide one::

    >>> from zope.app.testing import ztapi
    >>> from zope.interface import Interface
    >>> from contentratings.interfaces import IRatingCategory, IRatingManager
    >>> from contentratings.tests.test_category import DummyManager
    >>> ztapi.provideAdapter((IRatingCategory, Interface), IRatingManager,
    ...                      DummyManager)

    >>> manager = category(my_container)
    >>> isinstance(manager, DummyManager)
    True
    >>> manager.category is category
    True
    >>> manager.context is my_container
    True

The real adapter will dynamically provide the IRatingType interface
determined from the category storage, so that the category can be
registered as a named adapter to that interface.
