Changeset 5173
- Timestamp:
- 05/08/07 06:19:34 (1 year ago)
- Files:
-
- django/trunk/django/test/testcases.py (modified) (2 diffs)
- django/trunk/django/test/utils.py (modified) (3 diffs)
- django/trunk/docs/testing.txt (modified) (7 diffs)
- django/trunk/tests/modeltests/test_client/models.py (modified) (2 diffs)
- django/trunk/tests/modeltests/test_client/urls.py (modified) (1 diff)
- django/trunk/tests/modeltests/test_client/views.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/test/testcases.py
r5156 r5173 2 2 from urlparse import urlparse 3 3 from django.db import transaction 4 from django.core import management 4 from django.core import management, mail 5 5 from django.db.models import get_apps 6 6 from django.test.client import Client … … 34 34 35 35 class TestCase(unittest.TestCase): 36 def install_fixtures(self): 37 """If the Test Case class has a 'fixtures' member, clear the database and 38 install the named fixtures at the start of each test. 36 def _pre_setup(self): 37 """Perform any pre-test setup. This includes: 39 38 39 * If the Test Case class has a 'fixtures' member, clearing the 40 database and installing the named fixtures at the start of each test. 41 * Clearing the mail test outbox. 42 40 43 """ 41 44 management.flush(verbosity=0, interactive=False) 42 45 if hasattr(self, 'fixtures'): 43 46 management.load_data(self.fixtures, verbosity=0) 44 47 mail.outbox = [] 48 45 49 def run(self, result=None): 46 """Wrapper around default run method so that user-defined Test Cases47 automatically call install_fixtures without having to include a call to48 super().50 """Wrapper around default run method to perform common Django test set up. 51 This means that user-defined Test Cases aren't required to include a call 52 to super().setUp(). 49 53 50 54 """ 51 55 self.client = Client() 52 self. install_fixtures()56 self._pre_setup() 53 57 super(TestCase, self).run(result) 54 58 django/trunk/django/test/utils.py
r4541 r5173 2 2 from django.conf import settings 3 3 from django.db import connection, transaction, backend 4 from django.core import management 4 from django.core import management, mail 5 5 from django.dispatch import dispatcher 6 6 from django.test import signals … … 19 19 return self.nodelist.render(context) 20 20 21 class TestSMTPConnection(object): 22 """A substitute SMTP connection for use during test sessions. 23 The test connection stores email messages in a dummy outbox, 24 rather than sending them out on the wire. 25 26 """ 27 def __init__(*args, **kwargs): 28 pass 29 def open(self): 30 "Mock the SMTPConnection open() interface" 31 pass 32 def close(self): 33 "Mock the SMTPConnection close() interface" 34 pass 35 def send_messages(self, messages): 36 "Redirect messages to the dummy outbox" 37 mail.outbox.extend(messages) 38 21 39 def setup_test_environment(): 22 40 """Perform any global pre-test setup. This involves: 23 41 24 42 - Installing the instrumented test renderer 43 - Diverting the email sending functions to a test buffer 25 44 26 45 """ … … 28 47 Template.render = instrumented_test_render 29 48 49 mail.original_SMTPConnection = mail.SMTPConnection 50 mail.SMTPConnection = TestSMTPConnection 51 52 mail.outbox = [] 53 30 54 def teardown_test_environment(): 31 55 """Perform any global post-test teardown. This involves: 32 56 33 57 - Restoring the original test renderer 58 - Restoring the email sending functions 34 59 35 60 """ 36 61 Template.render = Template.original_render 37 62 del Template.original_render 63 64 mail.SMTPConnection = mail.original_SMTPConnection 65 del mail.original_SMTPConnection 66 67 del mail.outbox 38 68 39 69 def _set_autocommit(connection): django/trunk/docs/testing.txt
r5169 r5173 178 178 * `Test Client`_ 179 179 * `TestCase`_ 180 * `Email services`_ 180 181 181 182 Test Client … … 258 259 259 260 ``login(**credentials)`` 260 ** New in Django development version**261 **New in Django development version** 261 262 262 263 On a production site, it is likely that some views will be protected from … … 290 291 ~~~~~~~~~~~~~~~~~ 291 292 292 The ``get()`` , ``post()`` and ``login()`` methods all return a Response293 object. This Response object has the following properties that can be used 294 for testingpurposes:293 The ``get()`` and ``post()`` methods both return a Response object. This 294 Response object has the following properties that can be used for testing 295 purposes: 295 296 296 297 =============== ========================================================== … … 397 398 Default Test Client 398 399 ~~~~~~~~~~~~~~~~~~~ 399 ** New in Django development version**400 **New in Django development version** 400 401 401 402 Every test case in a ``django.test.TestCase`` instance has access to an … … 454 455 another test, or the order of test execution. 455 456 457 Emptying the test outbox 458 ~~~~~~~~~~~~~~~~~~~~~~~~ 459 **New in Django development version** 460 461 At the start of each test case, in addition to installing fixtures, 462 Django clears the contents of the test email outbox. 463 464 For more detail on email services during tests, see `Email services`_. 465 456 466 Assertions 457 467 ~~~~~~~~~~ 458 ** New in Django development version**468 **New in Django development version** 459 469 460 470 Normal Python unit tests have a wide range of assertions, such as … … 492 502 response. 493 503 504 Email services 505 -------------- 506 **New in Django development version** 507 508 If your view makes use of the `Django email services`_, you don't really 509 want email to be sent every time you run a test using that view. 510 511 When the Django test framework is initialized, it transparently replaces the 512 normal `SMTPConnection`_ class with a dummy implementation that redirects all 513 email to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``, 514 is a simple list of all `EmailMessage`_ instances that have been sent. 515 For example, during test conditions, it would be possible to run the following 516 code:: 517 518 from django.core import mail 519 520 # Send message 521 mail.send_mail('Subject here', 'Here is the message.', 'from@example.com', 522 ['to@example.com'], fail_silently=False) 523 524 # One message has been sent 525 self.assertEqual(len(mail.outbox), 1) 526 # Subject of first message is correct 527 self.assertEqual(mail.outbox[0].subject, 'Subject here') 528 529 The ``mail.outbox`` object does not exist under normal execution conditions. 530 The outbox is created during test setup, along with the dummy `SMTPConnection`_. 531 When the test framework is torn down, the standard `SMTPConnection`_ class 532 is restored, and the test outbox is destroyed. 533 534 As noted `previously`_, the test outbox is emptied at the start of every 535 test in a Django TestCase. To empty the outbox manually, assign the empty list 536 to mail.outbox:: 537 538 from django.core import mail 539 540 # Empty the test outbox 541 mail.outbox = [] 542 543 .. _`Django email services`: ../email/ 544 .. _`SMTPConnection`: ../email/#the-emailmessage-and-smtpconnection-classes 545 .. _`EmailMessage`: ../email/#the-emailmessage-and-smtpconnection-classes 546 .. _`previously`: #emptying-the-test-outbox 494 547 495 548 Running tests … … 611 664 ``setup_test_environment()`` 612 665 Performs any global pre-test setup, such as the installing the 613 instrumentation of the template rendering system. 666 instrumentation of the template rendering system and setting up 667 the dummy SMTPConnection. 614 668 615 669 ``teardown_test_environment()`` 616 670 Performs any global post-test teardown, such as removing the instrumentation 617 of the template rendering system .671 of the template rendering system and restoring normal email services. 618 672 619 673 ``create_test_db(verbosity=1, autoclobber=False)`` django/trunk/tests/modeltests/test_client/models.py
r5156 r5173 21 21 """ 22 22 from django.test import Client, TestCase 23 from django.core import mail 23 24 24 25 class ClientTest(TestCase): … … 233 234 except KeyError: 234 235 pass 236 237 def test_mail_sending(self): 238 "Test that mail is redirected to a dummy outbox during test setup" 239 240 response = self.client.get('/test_client/mail_sending_view/') 241 self.assertEqual(response.status_code, 200) 242 243 self.assertEqual(len(mail.outbox), 1) 244 self.assertEqual(mail.outbox[0].subject, 'Test message') 245 self.assertEqual(mail.outbox[0].body, 'This is a test email') 246 self.assertEqual(mail.outbox[0].from_email, 'from@example.com') 247 self.assertEqual(mail.outbox[0].to[0], 'first@example.com') 248 self.assertEqual(mail.outbox[0].to[1], 'second@example.com') 249 250 def test_mass_mail_sending(self): 251 "Test that mass mail is redirected to a dummy outbox during test setup" 252 253 response = self.client.get('/test_client/mass_mail_sending_view/') 254 self.assertEqual(response.status_code, 200) 255 256 self.assertEqual(len(mail.outbox), 2) 257 self.assertEqual(mail.outbox[0].subject, 'First Test message') 258 self.assertEqual(mail.outbox[0].body, 'This is the first test email') 259 self.assertEqual(mail.outbox[0].from_email, 'from@example.com') 260 self.assertEqual(mail.outbox[0].to[0], 'first@example.com') 261 self.assertEqual(mail.outbox[0].to[1], 'second@example.com') 262 263 self.assertEqual(mail.outbox[1].subject, 'Second Test message') 264 self.assertEqual(mail.outbox[1].body, 'This is the second test email') 265 self.assertEqual(mail.outbox[1].from_email, 'from@example.com') 266 self.assertEqual(mail.outbox[1].to[0], 'second@example.com') 267 self.assertEqual(mail.outbox[1].to[1], 'third@example.com') 268 django/trunk/tests/modeltests/test_client/urls.py
r5156 r5173 12 12 (r'^login_protected_view/$', views.login_protected_view), 13 13 (r'^session_view/$', views.session_view), 14 (r'^broken_view/$', views.broken_view) 14 (r'^broken_view/$', views.broken_view), 15 (r'^mail_sending_view/$', views.mail_sending_view), 16 (r'^mass_mail_sending_view/$', views.mass_mail_sending_view) 15 17 ) django/trunk/tests/modeltests/test_client/views.py
r5156 r5173 1 1 from xml.dom.minidom import parseString 2 from django.core.mail import EmailMessage, SMTPConnection 2 3 from django.template import Context, Template 3 4 from django.http import HttpResponse, HttpResponseRedirect … … 125 126 """A view which just raises an exception, simulating a broken view.""" 126 127 raise KeyError("Oops! Looks like you wrote some bad code.") 128 129 def mail_sending_view(request): 130 EmailMessage( 131 "Test message", 132 "This is a test email", 133 "from@example.com", 134 ['first@example.com', 'second@example.com']).send() 135 return HttpResponse("Mail sent") 136 137 def mass_mail_sending_view(request): 138 m1 = EmailMessage( 139 'First Test message', 140 'This is the first test email', 141 'from@example.com', 142 ['first@example.com', 'second@example.com']) 143 m2 = EmailMessage( 144 'Second Test message', 145 'This is the second test email', 146 'from@example.com', 147 ['second@example.com', 'third@example.com']) 148 149 c = SMTPConnection() 150 c.send_messages([m1,m2]) 151 152 return HttpResponse("Mail sent")
