Warning
This documentation does not refer to the most recent version of Pylons. Current Documentation
Pylons provides powerful unit testing capabilities for your web application utilizing paste.fixture to emulate requests to your web application. You can then ensure that the response was handled appropriately and that the controller set things up properly.
To run the test suite for your web application, Pylons utilizes the nose test runner/discovery package. Running nosetests in your project directory will run all the tests you create in the tests directory. If you don't have nose installed on your system, it can be installed via setuptools with:
easy_install -U nose
Note: paste.fixture is currently incompatible with Windows, we are working on remedying this.
Pylons will provide several additional attributes for the paste.fixture response object that let you access various objects that were created during the web request:
List of component calls, including any scomp, comp, and subexec thats executed during the request. Each item of the list is a dict with the keys:
To use them, merely access the attributes of the response after you've used a get/post command:
response = app.get('/some/url')
assert response.session['var'] == 4
First let's create a new project and controller for this example:
paster create --template=pylons TestExample cd TestExample paster controller comments
You'll see that it creates two files when you create a controller. The stub controller, and a test for it under testexample/tests/functional/.
Modify the testexample/controllers/comments.py file so it looks like this:
from testexample.lib.base import *
class CommentsController(BaseController):
def index(self):
m.write('Basic output')
def sess(self):
session['name'] = 'Joe Smith'
session.save()
m.write('Saved a session')
Then write a basic set of tests to ensure that the controller actions are functioning properly, modify testexample/tests/functions/test_comments.py to match the following:
from testexample.tests import *
class TestCommentsController(TestController):
def test_index(self):
response = self.app.get(url_for(controller='/comments'))
assert 'Basic output' in response
def test_sess(self):
response = self.app.get(url_for(controller='/comments', action='sess'))
assert response.session['name'] == 'Joe Smith'
assert 'Saved a session' in response
Run nosetests in your main project directory and you should see them all pass:
.. ---------------------------------------------------------------------- Ran 2 tests in 2.999s OK
Unfortunately, nosetests (as of 0.8.6 at least) cannot provide detailed information about the results of an assertion should it fail when you use this format for testing. For example, add the following test to the test_sess function:
assert response.session.has_key('address') == True
When you run nosetests you will get the following, not-very-helpful response:
.F
======================================================================
FAIL: test_sess (testexample.tests.functional.test_comments.TestCommentsController)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/TestExample/testexample/tests/functional/test_comments.py", line 12, in test_sess
assert response.session.has_key('address') == True
AssertionError:
----------------------------------------------------------------------
Ran 2 tests in 1.417s
FAILED (failures=1)
Since our TestController we inherited from is a standard Python unit testing controller we can use the assertEqual statement which will provide more information. The new test line looks like this:
self.assertEqual(response.session.has_key('address'), True)
Which provides the more useful failure message:
.F
======================================================================
FAIL: test_sess (testexample.tests.functional.test_comments.TestCommentsController)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/TestExample/testexample/tests/functional/test_comments.py", line 12, in test_sess
self.assertEqual(response.session.has_key('address'), True)
AssertionError: False != True
For more details on running tests using get/post, and testing the response, headers, etc., see the Paste document on web application testing: