summaryrefslogtreecommitdiff
path: root/django/test
diff options
context:
space:
mode:
authorJason Pellerin <jpellerin@gmail.com>2006-09-08 16:35:39 +0000
committerJason Pellerin <jpellerin@gmail.com>2006-09-08 16:35:39 +0000
commit84f7a2133c4d553a234165bb8cbfaf70681bb028 (patch)
tree53d08c1ffc275a4e1d62d7f48ea81172a5919051 /django/test
parentae3896cb74d4bc42acaf6fade0d2a57e28045b2a (diff)
[multi-db] Merge trunk to [3737]. Some tests still failing.
git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3739 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/test')
-rw-r--r--django/test/client.py48
-rw-r--r--django/test/signals.py1
-rw-r--r--django/test/simple.py4
-rw-r--r--django/test/utils.py52
4 files changed, 74 insertions, 31 deletions
diff --git a/django/test/client.py b/django/test/client.py
index 871f6cfb9b..3dfe764a38 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -1,10 +1,9 @@
from cStringIO import StringIO
-from django.contrib.admin.views.decorators import LOGIN_FORM_KEY, _encode_post_data
from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import WSGIRequest
from django.dispatch import dispatcher
from django.http import urlencode, SimpleCookie
-from django.template import signals
+from django.test import signals
from django.utils.functional import curry
class ClientHandler(BaseHandler):
@@ -96,7 +95,7 @@ class Client:
HTML rendered to the end-user.
"""
def __init__(self, **defaults):
- self.handler = TestHandler()
+ self.handler = ClientHandler()
self.defaults = defaults
self.cookie = SimpleCookie()
@@ -126,7 +125,7 @@ class Client:
data = {}
on_template_render = curry(store_rendered_templates, data)
dispatcher.connect(on_template_render, signal=signals.template_rendered)
-
+
response = self.handler(environ)
# Add any rendered template detail to the response
@@ -180,29 +179,38 @@ class Client:
def login(self, path, username, password, **extra):
"""
A specialized sequence of GET and POST to log into a view that
- is protected by @login_required or a similar access decorator.
+ is protected by a @login_required access decorator.
- path should be the URL of the login page, or of any page that
- is login protected.
+ path should be the URL of the page that is login protected.
- Returns True if login was successful; False if otherwise.
+ Returns the response from GETting the requested URL after
+ login is complete. Returns False if login process failed.
"""
- # First, GET the login page.
- # This is required to establish the session.
+ # First, GET the page that is login protected.
+ # This page will redirect to the login page.
response = self.get(path)
- if response.status_code != 200:
+ if response.status_code != 302:
return False
+
+ login_path, data = response['Location'].split('?')
+ next = data.split('=')[1]
- # Set up the block of form data required by the login page.
+ # Second, GET the login page; required to set up cookies
+ response = self.get(login_path, **extra)
+ if response.status_code != 200:
+ return False
+
+ # Last, POST the login data.
form_data = {
'username': username,
'password': password,
- 'this_is_the_login_form': 1,
- 'post_data': _encode_post_data({LOGIN_FORM_KEY: 1})
+ 'next' : next,
}
- response = self.post(path, data=form_data, **extra)
-
- # login page should give response 200 (if you requested the login
- # page specifically), or 302 (if you requested a login
- # protected page, to which the login can redirect).
- return response.status_code in (200,302)
+ response = self.post(login_path, data=form_data, **extra)
+
+ # Login page should 302 redirect to the originally requested page
+ if response.status_code != 302 or response['Location'] != path:
+ return False
+
+ # Since we are logged in, request the actual page again
+ return self.get(path)
diff --git a/django/test/signals.py b/django/test/signals.py
new file mode 100644
index 0000000000..40748ff4fe
--- /dev/null
+++ b/django/test/signals.py
@@ -0,0 +1 @@
+template_rendered = object() \ No newline at end of file
diff --git a/django/test/simple.py b/django/test/simple.py
index 2469f80b3a..043787414e 100644
--- a/django/test/simple.py
+++ b/django/test/simple.py
@@ -1,6 +1,7 @@
import unittest, doctest
from django.conf import settings
from django.core import management
+from django.test.utils import setup_test_environment, teardown_test_environment
from django.test.utils import create_test_db, destroy_test_db
from django.test.testcases import OutputChecker, DocTestRunner
@@ -51,6 +52,7 @@ def run_tests(module_list, verbosity=1, extra_tests=[]):
the module. A list of 'extra' tests may also be provided; these tests
will be added to the test suite.
"""
+ setup_test_environment()
settings.DEBUG = False
suite = unittest.TestSuite()
@@ -66,3 +68,5 @@ def run_tests(module_list, verbosity=1, extra_tests=[]):
management.syncdb(verbosity, interactive=False)
unittest.TextTestRunner(verbosity=verbosity).run(suite)
destroy_test_db(old_name, verbosity)
+
+ teardown_test_environment()
diff --git a/django/test/utils.py b/django/test/utils.py
index bde323fa4e..d7a4a9c963 100644
--- a/django/test/utils.py
+++ b/django/test/utils.py
@@ -1,11 +1,41 @@
import sys, time
from django.conf import settings
+
from django.db import backend, connect, connection, connection_info, connections
+from django.dispatch import dispatcher
+from django.test import signals
+from django.template import Template
# The prefix to put on the default database name when creating
# the test database.
TEST_DATABASE_PREFIX = 'test_'
+def instrumented_test_render(self, context):
+ """An instrumented Template render method, providing a signal
+ that can be intercepted by the test system Client
+
+ """
+ dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context)
+ return self.nodelist.render(context)
+
+def setup_test_environment():
+ """Perform any global pre-test setup. This involves:
+
+ - Installing the instrumented test renderer
+
+ """
+ Template.original_render = Template.render
+ Template.render = instrumented_test_render
+
+def teardown_test_environment():
+ """Perform any global post-test teardown. This involves:
+
+ - Restoring the original test renderer
+
+ """
+ Template.render = Template.original_render
+ del Template.original_render
+
def _set_autocommit(connection):
"Make sure a connection is in autocommit mode."
if hasattr(connection.connection, "autocommit"):
@@ -55,12 +85,13 @@ def create_test_db(verbosity=1, autoclobber=False):
else:
print "Tests cancelled."
sys.exit(1)
- # Close the old connection
- connection.close()
+
+ connection.close()
+ settings.DATABASE_NAME = TEST_DATABASE_NAME
- # Get a cursor (even though we don't need one yet). This has
- # the side effect of initializing the test database.
- cursor = connection.cursor()
+ # Get a cursor (even though we don't need one yet). This has
+ # the side effect of initializing the test database.
+ cursor = connection.cursor()
# Fill OTHER_DATABASES with the TEST_DATABASES settings,
# and connect each named connection to the test database, using
@@ -87,15 +118,14 @@ def destroy_test_db(old_database_name, old_databases, verbosity=1):
# connected to it.
if verbosity >= 1:
print "Destroying test database..."
- if settings.DATABASE_ENGINE != "sqlite3":
- connection.close()
- TEST_DATABASE_NAME = settings.DATABASE_NAME
- settings.DATABASE_NAME = old_database_name
+ connection.close()
+ TEST_DATABASE_NAME = settings.DATABASE_NAME
+ settings.DATABASE_NAME = old_database_name
+
+ if settings.DATABASE_ENGINE != "sqlite3":
settings.OTHER_DATABASES = old_databases
cursor = connection.cursor()
_set_autocommit(connection)
time.sleep(1) # To avoid "database is being accessed by other users" errors.
cursor.execute("DROP DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))
connection.close()
-
-