So far, we've been reading through the pylons source and then hacking
our way around each problem, such as by calling directly into mako's
render method or manually calling pylons.config._push_object. Is there
a better way to get a non-crippled environment in our tests? Thanks.
--
Yang Zhang
http://yz.mit.edu/
This only addresses the pylons.config issue; e.g., rendering via
pylons.templating is still having problems.
http://yz.mit.edu/
--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To post to this group, send email to pylons-...@googlegroups.com.
To unsubscribe from this group, send email to pylons-discus...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
> But obviously the better approach would be to keep the changes in the
> code I control :)
This is exactly the approach I'm taking to fix testing up for Pylons 1.1. Here is what the tests/__init__.py looks like in the 1.1 branch for example (which will work fine for projects right now using Pylons):
"""Pylons application test package
This package assumes the Pylons environment is already loaded, such as
when this script is imported from the `nosetests --with-pylons=test.ini`
command.
This module initializes the application via ``websetup`` (`paster
setup-app`) and provides the base testing objects.
"""
from unittest import TestCase
import os
import sys
import pylons
from pylons.i18n.translation import _get_translator
from paste.deploy import loadapp
from pylons import url
from routes.util import URLGenerator
from webtest import TestApp
from {{package}}.config.environment import load_environment
__all__ = ['environ', 'url', 'TestController']
environ = {}
here_dir = os.path.dirname(os.path.abspath(__file__))
conf_dir = os.path.dirname(os.path.dirname(here_dir))
sys.path.insert(0, conf_dir)
class TestController(TestCase):
def __init__(self, *args, **kwargs):
wsgiapp = loadapp('config:test.ini', relative_to=conf_dir)
config = wsgiapp.config
pylons.app_globals._push_object(config['pylons.app_globals'])
pylons.config._push_object(config)
# Initialize a translator for tests that utilize i18n
translator = _get_translator(pylons.config.get('lang'))
pylons.translator._push_object(translator)
url._push_object(URLGenerator(config['routes.map'], environ))
self.app = TestApp(wsgiapp)
TestCase.__init__(self, *args, **kwargs)
Replace {{package}} with the name of your project. Note that this sets up the following globals:
config, app_globals, url, and translator (needed for set_lang/get_lang/i18n)
Using this, you should be able to remove the 'with-pylons' line from the setup.cfg, as the plugin shouldn't be needed (unless you're doing doc testing of your project...).
Making testing great is definitely a top priority for Pylons, and some of the other new stuff coming in 1.1 will lead to substantially easier unit testing in addition to the functional/integrated testing Pylons emphasizes with the usage of TestApp.
Cheers,
Ben
Yes. It keeps improving incrementally but there's always something
left out, and that ends up being what somebody needs for their tests.
The problem is that while custom test code can look someplace else for
the objects, anything it calls will expect things in their traditional
place. I generally use the SOPs only in controllers and templates, to
minimize my functions depending on them.
Ben wrote:
> fix testing up for Pylons 1.1
Hooray, hooray. That code still doesn't address 'tmpl_context' which
was the original question. Although 'tmpl_context' shouldn't really be
used outside a request. However, for the sake of completeness, we
should probably either create an empty context or push a dummy object
that says "don't use me outside of a request".
Didip wrote:
> I have similar problem with app_globals. I ended up moving everything in app_globals to meta module, which is available when running nosetests.
I did essentially the same thing, making a separate model object that
can be put on app_globals during runtime, but also instantiated
standalone for testing the object itself.
Wyatt wrote:
> pylons.app_globals._push_object(config['pylons.app_globals'])
I was reluctant to do that myself without an "official" recommendation
that this was the right method, but I suppose it works.
> (Unfortunately, and frustratingly, Paste seems to be the
> popular choice in the non-Django full-featured-frameworks ... so I can
> only assume that they're all going to get mired down in SOP confusion
> & misdirection.)
Paste is a collection of independent things (which Ian is gradually
moving out of Paste to their own packages). Most Paste frameworks do
not use SOPs. SOPs were created for Pylons to address the rare case of
multiple WSGI applications (or instances of the same application)
using shared globals in the same process. E.g., 'app_globals' is
specific to the application instance, not to the worker thread, so it
has to be switched as each instance is requested. Pylons chose to use
shared globals due to their popularity in CherryPy, but they do raise
this problem when combining applications. So if a framework avoids
shared globals, it doesn't need SOPs. In some frameworks, the context
is passed as action arguments, or instance attributes on the
controller, or global functions that find the context and return it.
--
Mike Orr <slugg...@gmail.com>
This is inconsistent with the module docstring you just pasted:
> """Pylons application test package
>
> This package assumes the Pylons environment is already loaded, such as
> when this script is imported from the `nosetests --with-pylons=test.ini`
> command.
Marius Gedminas
--
When I die I want to go peacefully
in my sleep like my ol' Grand
Dad...not screaming in terror like
his passengers.
-- seen in a sig of Branden Robinson
> This is inconsistent with the module docstring you just pasted:
Good catch, I'll remove that from the doc string as I updated the code and failed to read the doc string. :)
Cheers,
Ben