[PEAK] proper unit testing

Phillip J. Eby pje at telecommunity.com
Thu Nov 4 21:27:21 EST 2004


At 05:56 PM 11/4/04 -0500, R. David Murray wrote:
>     if _root is None:
>         from peak.api import config
>         _root = binding.Configurable(config.makeRoot())
>         config.loadConfigFile(_root,
>             config.packageFile(__name__, 'tests.ini'))

The problem here is that you're loading 'tests.ini' into a separate 
component from the service area/root component, but 'tests.ini' contains 
named services.  So, when the service area (root component) tries to create 
the named service, it can't find the factory because it's registered in a 
child component.

There are two ways you can fix this.  Either change from using 
'binding.Configurable' to 'config.ServiceArea', or load 'tests.ini' into 
the root, e.g.:

    _root = config.makeRoot(
        iniFiles=[
            config.packageFile('peak','peak.ini'),
            config.packageFile(__name__,'tests.ini'),
        ]
    )


Conceptual background: many kinds of services want to be "singletons", in 
the sense that there is only one instance of them created, within some 
"scope".  So, PEAK divides the configuration hierarchy into logical 
subtrees known as "service areas" (see config.IServiceArea).

All the children of a service area share the same "global" services.  A 
"global" service is defined using [Named Services] or [Component 
Factories].  The factory or expression is used to initialize that service 
when it is first requested within a given service area.

By default, unless you explicitly create an IServiceArea (e.g. via 
config.ServiceArea()), the configuration root is the only IServiceArea, so 
all services are global.  However, since configuration loaded "below" the 
root doesn't change the root's configuration, your loading tests.ini into a 
subcomponent doesn't change how the root is configured, and it thus doesn't 
know how to find the factory for the named service you defined.

What you may not know is that the 'commands' framework, when it runs an 
.ini file as an application, it actually loads the .ini into a new 
'config.ServiceArea'.  This ensures that the loaded application runs within 
its own fresh "scope", with its own copies of any global services, distinct 
from those in the command object's configuration hierarchy.  Of course, any 
configuration from the root will be "inherited" by the child service area 
(such as the configuration for how to *create* the global services), but 
the service instances themselves will be separate from those in the root 
service area.




More information about the PEAK mailing list