Skip to content

Instantly share code, notes, and snippets.

@groner
Created August 10, 2010 13:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save groner/517237 to your computer and use it in GitHub Desktop.
Save groner/517237 to your computer and use it in GitHub Desktop.
Hooks for lettuce to run a test pylons server
'''Hooks for lettuce to run a test pylons server'''
import threading
from os import getcwd
import pylons.test
from paste.deploy.loadwsgi import loadapp
from paste.httpserver import serve
from paste.script.appinstall import SetupCommand
from routes.util import URLGenerator
from lettuce import *
@before.all
def start_test_server():
'''Start a test server
Adds the following to world:
- app: The WSGI application defined in test.ini
- environ:
- url: A routes url generator for the app
- server: The paste web server
- server_thread: The thread from which the paste server is started
'''
if not hasattr(world, 'server_thread'):
# create the server first, so we can give the app a baseurl hint
# (needed to configure the cas plugin to talk to the cas stub server)
world.server = serve(None, port=0, start_loop=False)
world.environ = {}
world.environ.update(SERVER_NAME=str(world.server.server_name))
world.environ.update(SERVER_PORT=str(world.server.server_port))
if not hasattr(world, 'app'):
if pylons.test.pylonsapp:
print "Using pylons.test.pylonsapp"
world.app = pylons.test.pylonsapp
else:
print "Loading test app from test.ini"
global_conf = {'test.baseurl':'http://%s:%s/' %
(world.server.server_name, world.server.server_port)}
world.app = loadapp('config:test.ini', relative_to=getcwd(),
global_conf=global_conf)
# setup-app looks here for an app before loading it, we need to
# use the same app otherwise we won't be using the same in
# memory database
pylons.test.pylonsapp = world.app
world.server.wsgi_application = world.app
SetupCommand('setup-app').run([world.app.config['__file__']])
config = world.app.config
world.url = URLGenerator(config['routes.map'], world.environ)
world.server_thread = threading.Thread(target=world.server.serve_forever, name=repr(world.server))
print "Server starting"
world.server_thread.start()
@after.all
def stop_test_server(total):
if hasattr(world, 'server_thread'):
print "Server stopping"
world.server.server_close()
world.server_thread.join()
del world.server
del world.server_thread
@gabrielfalcao
Copy link

Awesome!!
Can I put it in lettuce's cookbook, at official documentation?

@zhenghao1
Copy link

Hi I'm a newbie when it comes to fiddling with the Pylons internals. How would I start the server with this code above, because I usually run "paster serve --reload development.ini" to start the server. How would this change the way I start my server?

@gabrielfalcao
Copy link

this is lettuce internals, mostly...
you basically just run lettuce, and the hooks above will take care of your server.

The thing is that lettuce has hooks, that can be registered thru decorators.
The decorators above: before.all is creating a thread that runs the pylons server, and closes that server on the action: after.all

@groner
Copy link
Author

groner commented Jun 14, 2011

This code tries to make everything automatic. It uses a random available port for the server and I used a sqlite:///:memory: database, this allows you to have more than one set of tests running at once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment