Refs #2333 - Added model test for the test Client.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3708 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2006-09-02 09:34:40 +00:00
parent d043200077
commit 826b9ff5e5
10 changed files with 198 additions and 2 deletions

View File

View File

@ -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)

View File

@ -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)

View File

@ -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),
)

View File

@ -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))

View File

@ -6,6 +6,7 @@ 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)
@ -71,17 +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
# 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:
@ -112,6 +119,9 @@ def django_tests(verbosity, tests_to_run):
# 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 ...]"

1
tests/templates/404.html Normal file
View File

@ -0,0 +1 @@
Django Internal Tests: 404 Error

1
tests/templates/500.html Normal file
View File

@ -0,0 +1 @@
Django Internal Tests: 500 Error

View File

@ -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>

10
tests/urls.py Normal file
View File

@ -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'),
)