[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