summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorChristopher Long <indirecthit@gmail.com>2006-09-07 01:36:27 +0000
committerChristopher Long <indirecthit@gmail.com>2006-09-07 01:36:27 +0000
commite12c2f83e0109a8e78954c8a176aa42b28ea96dc (patch)
treee50a312784e3251ba7950fe99f400421ac141992 /tests
parent5c13ad5ea2d65cd705c6362ef4194b45725177f8 (diff)
[per-object-permissions] Merged to trunk [3731]
git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@3732 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
-rw-r--r--tests/modeltests/get_latest/models.py8
-rw-r--r--tests/modeltests/test_client/__init__.py0
-rw-r--r--tests/modeltests/test_client/management.py10
-rw-r--r--tests/modeltests/test_client/models.py101
-rw-r--r--tests/modeltests/test_client/urls.py9
-rw-r--r--tests/modeltests/test_client/views.py35
-rw-r--r--tests/regressiontests/templates/tests.py54
-rwxr-xr-xtests/runtests.py22
-rw-r--r--tests/templates/404.html1
-rw-r--r--tests/templates/500.html1
-rw-r--r--tests/templates/login.html19
-rw-r--r--tests/urls.py10
12 files changed, 246 insertions, 24 deletions
diff --git a/tests/modeltests/get_latest/models.py b/tests/modeltests/get_latest/models.py
index ff8d8f28eb..84c6273818 100644
--- a/tests/modeltests/get_latest/models.py
+++ b/tests/modeltests/get_latest/models.py
@@ -3,9 +3,9 @@
Models can have a ``get_latest_by`` attribute, which should be set to the name
of a DateField or DateTimeField. If ``get_latest_by`` exists, the model's
-module will get a ``get_latest()`` function, which will return the latest
-object in the database according to that field. "Latest" means "having the
-date farthest into the future."
+manager will get a ``latest()`` method, which will return the latest object in
+the database according to that field. "Latest" means "having the date farthest
+into the future."
"""
from django.db import models
@@ -30,7 +30,7 @@ class Person(models.Model):
return self.name
__test__ = {'API_TESTS':"""
-# Because no Articles exist yet, get_latest() raises ArticleDoesNotExist.
+# Because no Articles exist yet, latest() raises ArticleDoesNotExist.
>>> Article.objects.latest()
Traceback (most recent call last):
...
diff --git a/tests/modeltests/test_client/__init__.py b/tests/modeltests/test_client/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/modeltests/test_client/__init__.py
diff --git a/tests/modeltests/test_client/management.py b/tests/modeltests/test_client/management.py
new file mode 100644
index 0000000000..9b5a5c498e
--- /dev/null
+++ b/tests/modeltests/test_client/management.py
@@ -0,0 +1,10 @@
+from django.dispatch import dispatcher
+from django.db.models import signals
+import models as test_client_app
+from django.contrib.auth.models import User
+
+def setup_test(app, created_models, verbosity):
+ # Create a user account for the login-based tests
+ User.objects.create_user('testclient','testclient@example.com', 'password')
+
+dispatcher.connect(setup_test, sender=test_client_app, signal=signals.post_syncdb)
diff --git a/tests/modeltests/test_client/models.py b/tests/modeltests/test_client/models.py
new file mode 100644
index 0000000000..c5b1a241ca
--- /dev/null
+++ b/tests/modeltests/test_client/models.py
@@ -0,0 +1,101 @@
+"""
+39. Testing using the Test Client
+
+The test client is a class that can act like a simple
+browser for testing purposes.
+
+It allows the user to compose GET and POST requests, and
+obtain the response that the server gave to those requests.
+The server Response objects are annotated with the details
+of the contexts and templates that were rendered during the
+process of serving the request.
+
+Client objects are stateful - they will retain cookie (and
+thus session) details for the lifetime of the Client instance.
+
+This is not intended as a replacement for Twill,Selenium, or
+other browser automation frameworks - it is here to allow
+testing against the contexts and templates produced by a view,
+rather than the HTML rendered to the end-user.
+
+"""
+from django.test.client import Client
+import unittest
+
+class ClientTest(unittest.TestCase):
+ def setUp(self):
+ "Set up test environment"
+ self.client = Client()
+
+ def test_get_view(self):
+ "GET a view"
+ response = self.client.get('/test_client/get_view/')
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['var'], 42)
+ self.assertEqual(response.template.name, 'GET Template')
+ self.failUnless('This is a test.' in response.content)
+
+ def test_get_post_view(self):
+ "GET a view that normally expects POSTs"
+ response = self.client.get('/test_client/post_view/', {})
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.template.name, 'Empty POST Template')
+
+ def test_empty_post(self):
+ "POST an empty dictionary to a view"
+ response = self.client.post('/test_client/post_view/', {})
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.template.name, 'Empty POST Template')
+
+ def test_post_view(self):
+ "POST some data to a view"
+ post_data = {
+ 'value': 37
+ }
+ response = self.client.post('/test_client/post_view/', post_data)
+
+ # Check some response details
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['data'], '37')
+ self.assertEqual(response.template.name, 'POST Template')
+ self.failUnless('Data received' in response.content)
+
+ def test_redirect(self):
+ "GET a URL that redirects elsewhere"
+ response = self.client.get('/test_client/redirect_view/')
+
+ # Check that the response was a 302 (redirect)
+ self.assertEqual(response.status_code, 302)
+
+ def test_unknown_page(self):
+ "GET an invalid URL"
+ response = self.client.get('/test_client/unknown_view/')
+
+ # Check that the response was a 404
+ self.assertEqual(response.status_code, 404)
+
+ def test_view_with_login(self):
+ "Request a page that is protected with @login_required"
+
+ # Get the page without logging in. Should result in 302.
+ response = self.client.get('/test_client/login_protected_view/')
+ self.assertEqual(response.status_code, 302)
+
+ # Request a page that requires a login
+ response = self.client.login('/test_client/login_protected_view/', 'testclient', 'password')
+ self.assertTrue(response)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['user'].username, 'testclient')
+ self.assertEqual(response.template.name, 'Login Template')
+
+ def test_view_with_bad_login(self):
+ "Request a page that is protected with @login, but use bad credentials"
+
+ response = self.client.login('/test_client/login_protected_view/', 'otheruser', 'nopassword')
+ self.assertFalse(response)
diff --git a/tests/modeltests/test_client/urls.py b/tests/modeltests/test_client/urls.py
new file mode 100644
index 0000000000..09bba5c007
--- /dev/null
+++ b/tests/modeltests/test_client/urls.py
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import *
+import views
+
+urlpatterns = patterns('',
+ (r'^get_view/$', views.get_view),
+ (r'^post_view/$', views.post_view),
+ (r'^redirect_view/$', views.redirect_view),
+ (r'^login_protected_view/$', views.login_protected_view),
+)
diff --git a/tests/modeltests/test_client/views.py b/tests/modeltests/test_client/views.py
new file mode 100644
index 0000000000..bf131032eb
--- /dev/null
+++ b/tests/modeltests/test_client/views.py
@@ -0,0 +1,35 @@
+from django.template import Context, Template
+from django.http import HttpResponse, HttpResponseRedirect
+from django.contrib.auth.decorators import login_required
+
+def get_view(request):
+ "A simple view that expects a GET request, and returns a rendered template"
+ t = Template('This is a test. {{ var }} is the value.', name='GET Template')
+ c = Context({'var': 42})
+
+ return HttpResponse(t.render(c))
+
+def post_view(request):
+ """A view that expects a POST, and returns a different template depending
+ on whether any POST data is available
+ """
+ if request.POST:
+ t = Template('Data received: {{ data }} is the value.', name='POST Template')
+ c = Context({'data': request.POST['value']})
+ else:
+ t = Template('Viewing POST page.', name='Empty POST Template')
+ c = Context()
+
+ return HttpResponse(t.render(c))
+
+def redirect_view(request):
+ "A view that redirects all requests to the GET view"
+ return HttpResponseRedirect('/test_client/get_view/')
+
+@login_required
+def login_protected_view(request):
+ "A simple view that is login protected."
+ t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
+ c = Context({'user': request.user})
+
+ return HttpResponse(t.render(c))
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 2d1ce192ef..5a8dd2d6a2 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -84,7 +84,7 @@ class Templates(unittest.TestCase):
'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
# Fail silently when a variable is not found in the current context
- 'basic-syntax04': ("as{{ missing }}df", {}, "asINVALIDdf"),
+ 'basic-syntax04': ("as{{ missing }}df", {}, ("asdf","asINVALIDdf")),
# A variable may not contain more than one word
'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
@@ -100,7 +100,7 @@ class Templates(unittest.TestCase):
'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
# Fail silently when a variable's attribute isn't found
- 'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, "INVALID"),
+ 'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, ("","INVALID")),
# Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
@@ -116,10 +116,10 @@ class Templates(unittest.TestCase):
'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
# Fail silently when a variable's dictionary key isn't found
- 'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, "INVALID"),
+ 'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, ("","INVALID")),
# Fail silently when accessing a non-simple method
- 'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, "INVALID"),
+ 'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ("","INVALID")),
# Basic filter usage
'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
@@ -158,7 +158,7 @@ class Templates(unittest.TestCase):
'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
# Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
- 'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "1INVALID2"),
+ 'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, ("12", "1INVALID2")),
# In methods that raise an exception without a "silent_variable_attribute" set to True,
# the exception propogates
@@ -464,6 +464,14 @@ class Templates(unittest.TestCase):
# translation of a constant string
'i18n13': ('{{ _("Page not found") }}', {'LANGUAGE_CODE': 'de'}, 'Seite nicht gefunden'),
+ ### HANDLING OF TEMPLATE_TAG_IF_INVALID ###################################
+
+ 'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')),
+ 'invalidstr02': ('{{ var|default_if_none:"Foo" }}', {}, ('','INVALID')),
+ 'invalidstr03': ('{% for v in var %}({{ v }}){% endfor %}', {}, ''),
+ 'invalidstr04': ('{% if var %}Yes{% else %}No{% endif %}', {}, 'No'),
+ 'invalidstr04': ('{% if var|default:"Foo" %}Yes{% else %}No{% endif %}', {}, 'Yes'),
+
### MULTILINE #############################################################
'multiline01': ("""
@@ -507,7 +515,7 @@ class Templates(unittest.TestCase):
'{{ item.foo }}' + \
'{% endfor %},' + \
'{% endfor %}',
- {}, 'INVALID:INVALIDINVALIDINVALIDINVALIDINVALIDINVALIDINVALID,'),
+ {}, ''),
### TEMPLATETAG TAG #######################################################
'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
@@ -592,30 +600,44 @@ class Templates(unittest.TestCase):
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
# Set TEMPLATE_STRING_IF_INVALID to a known string
- old_invalid, settings.TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID, 'INVALID'
+ old_invalid = settings.TEMPLATE_STRING_IF_INVALID
for name, vals in tests:
install()
+
+ if isinstance(vals[2], tuple):
+ normal_string_result = vals[2][0]
+ invalid_string_result = vals[2][1]
+ else:
+ normal_string_result = vals[2]
+ invalid_string_result = vals[2]
+
if 'LANGUAGE_CODE' in vals[1]:
activate(vals[1]['LANGUAGE_CODE'])
else:
activate('en-us')
- try:
- output = loader.get_template(name).render(template.Context(vals[1]))
- except Exception, e:
- if e.__class__ != vals[2]:
- failures.append("Template test: %s -- FAILED. Got %s, exception: %s" % (name, e.__class__, e))
- continue
+
+ for invalid_str, result in [('', normal_string_result),
+ ('INVALID', invalid_string_result)]:
+ settings.TEMPLATE_STRING_IF_INVALID = invalid_str
+ try:
+ output = loader.get_template(name).render(template.Context(vals[1]))
+ except Exception, e:
+ if e.__class__ != result:
+ failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s" % (invalid_str, name, e.__class__, e))
+ continue
+ if output != result:
+ failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (invalid_str, name, result, output))
+
if 'LANGUAGE_CODE' in vals[1]:
deactivate()
- if output != vals[2]:
- failures.append("Template test: %s -- FAILED. Expected %r, got %r" % (name, vals[2], output))
+
loader.template_source_loaders = old_template_loaders
deactivate()
settings.TEMPLATE_DEBUG = old_td
settings.TEMPLATE_STRING_IF_INVALID = old_invalid
- self.assertEqual(failures, [])
+ self.assertEqual(failures, [], '\n'.join(failures))
if __name__ == "__main__":
unittest.main()
diff --git a/tests/runtests.py b/tests/runtests.py
index 57087ef3a7..359fca2bf5 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -5,6 +5,8 @@ import unittest
MODEL_TESTS_DIR_NAME = 'modeltests'
REGRESSION_TESTS_DIR_NAME = 'regressiontests'
+TEST_DATABASE_NAME = 'django_test_db'
+TEST_TEMPLATE_DIR = 'templates'
MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME)
@@ -70,14 +72,23 @@ class InvalidModelTestCase(unittest.TestCase):
def django_tests(verbosity, tests_to_run):
from django.conf import settings
from django.db.models.loading import get_apps, load_app
+
old_installed_apps = settings.INSTALLED_APPS
+ old_test_database_name = settings.TEST_DATABASE_NAME
+ old_root_urlconf = settings.ROOT_URLCONF
+ old_template_dirs = settings.TEMPLATE_DIRS
- # load all the ALWAYS_INSTALLED_APPS
+ # Redirect some settings for the duration of these tests
+ settings.TEST_DATABASE_NAME = TEST_DATABASE_NAME
settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS
+ settings.ROOT_URLCONF = 'urls'
+ settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),)
+
+ # load all the ALWAYS_INSTALLED_APPS
get_apps()
- test_models = []
# Load all the test model apps
+ test_models = []
for model_dir, model_name in get_test_models():
model_label = '.'.join([model_dir, model_name])
try:
@@ -105,9 +116,12 @@ def django_tests(verbosity, tests_to_run):
from django.test.simple import run_tests
run_tests(test_models, verbosity, extra_tests=extra_tests)
- # Restore the old INSTALLED_APPS setting
+ # Restore the old settings
settings.INSTALLED_APPS = old_installed_apps
-
+ settings.TESTS_DATABASE_NAME = old_test_database_name
+ settings.ROOT_URLCONF = old_root_urlconf
+ settings.TEMPLATE_DIRS = old_template_dirs
+
if __name__ == "__main__":
from optparse import OptionParser
usage = "%prog [options] [model model model ...]"
diff --git a/tests/templates/404.html b/tests/templates/404.html
new file mode 100644
index 0000000000..da627e2222
--- /dev/null
+++ b/tests/templates/404.html
@@ -0,0 +1 @@
+Django Internal Tests: 404 Error \ No newline at end of file
diff --git a/tests/templates/500.html b/tests/templates/500.html
new file mode 100644
index 0000000000..ff028cbeb0
--- /dev/null
+++ b/tests/templates/500.html
@@ -0,0 +1 @@
+Django Internal Tests: 500 Error \ No newline at end of file
diff --git a/tests/templates/login.html b/tests/templates/login.html
new file mode 100644
index 0000000000..8a0974c9a1
--- /dev/null
+++ b/tests/templates/login.html
@@ -0,0 +1,19 @@
+<html>
+<head></head>
+<body>
+<h1>Django Internal Tests: Login</h1>
+{% if form.has_errors %}
+<p>Your username and password didn't match. Please try again.</p>
+{% endif %}
+
+<form method="post" action=".">
+<table>
+<tr><td><label for="id_username">Username:</label></td><td>{{ form.username }}</td></tr>
+<tr><td><label for="id_password">Password:</label></td><td>{{ form.password }}</td></tr>
+</table>
+
+<input type="submit" value="login" />
+<input type="hidden" name="next" value="{{ next }}" />
+</form>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/urls.py b/tests/urls.py
new file mode 100644
index 0000000000..39d5aaee6b
--- /dev/null
+++ b/tests/urls.py
@@ -0,0 +1,10 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ # test_client modeltest urls
+ (r'^test_client/', include('modeltests.test_client.urls')),
+
+ # Always provide the auth system login and logout views
+ (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
+ (r'^accounts/logout/$', 'django.contrib.auth.views.login'),
+)