Ticket #4788: testing-patches.diff
File testing-patches.diff, 14.2 KB (added by , 16 years ago) |
---|
-
django/test/simple.py
1 import unittest1 import sys, time, traceback, unittest 2 2 from django.conf import settings 3 3 from django.db.models import get_app, get_apps 4 4 from django.test import _doctest as doctest … … 140 140 old_name = settings.DATABASE_NAME 141 141 from django.db import connection 142 142 connection.creation.create_test_db(verbosity, autoclobber=not interactive) 143 result = unittest.TextTestRunner(verbosity=verbosity).run(suite)143 result = SkipTestRunner(verbosity=verbosity).run(suite) 144 144 connection.creation.destroy_test_db(old_name, verbosity) 145 145 146 146 teardown_test_environment() 147 147 148 148 return len(result.failures) + len(result.errors) 149 150 class SkipTestRunner: 151 """ 152 A test runner class that adds a Skipped category in the output layer. 153 154 Modeled after unittest.TextTestRunner. 155 156 Similarly to unittest.TextTestRunner, prints summary of the results at the end. 157 (Including a count of skipped tests.) 158 """ 159 160 def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1): 161 self.stream = unittest._WritelnDecorator(stream) 162 self.descriptions = descriptions 163 self.verbosity = verbosity 164 self.result = _SkipTestResult(self.stream, descriptions, verbosity) 165 166 def run(self, test): 167 "Run the given test case or test suite." 168 startTime = time.time() 169 test.run(self.result) 170 stopTime = time.time() 171 timeTaken = stopTime - startTime 172 173 self.result.printErrors() 174 self.stream.writeln(self.result.separator2) 175 run = self.result.testsRun 176 self.stream.writeln('Ran %d test%s in %.3fs' % 177 (run, run != 1 and 's' or '', timeTaken)) 178 self.stream.writeln() 179 if not self.result.wasSuccessful(): 180 self.stream.write('FAILED (') 181 failed, errored, skipped = map(len, (self.result.failures, self.result.errors, self.result.skipped)) 182 if failed: 183 self.stream.write('failures=%d' % failed) 184 if errored: 185 if failed: self.stream.write(', ') 186 self.stream.write('errors=%d' % errored) 187 if skipped: 188 if errored or failed: self.stream.write(', ') 189 self.stream.write('skipped=%d' % skipped) 190 self.stream.writeln(')') 191 else: 192 self.stream.writeln('OK') 193 return self.result 194 195 class _SkipTestResult(unittest._TextTestResult): 196 """ 197 A test result class that adds a Skipped category in the output layer. 198 199 Modeled after unittest._TextTestResult. 200 201 Similarly to unittest._TextTestResult, prints out the names of tests as they are 202 run and errors as they occur. 203 """ 204 205 def __init__(self, stream, descriptions, verbosity): 206 unittest._TextTestResult.__init__(self, stream, descriptions, verbosity) 207 self.skipped = [] 208 209 def addError(self, test, err): 210 # Determine if this is a skipped test 211 tracebacks = traceback.extract_tb(err[2]) 212 if tracebacks[-1][-1].startswith('raise SkippedTest'): 213 self.skipped.append((test, self._exc_info_to_string(err, test))) 214 if self.showAll: 215 self.stream.writeln('SKIPPED') 216 elif self.dots: 217 self.stream.write('S') 218 self.stream.flush() 219 else: 220 unittest.TestResult.addError(self, test, err) 221 if self.showAll: 222 self.stream.writeln('ERROR') 223 elif self.dots: 224 self.stream.write('E') 225 self.stream.flush() 226 227 def printErrors(self): 228 if self.dots or self.showAll: 229 self.stream.writeln() 230 self.printErrorList('SKIPPED', self.skipped) 231 self.printErrorList('ERROR', self.errors) 232 self.printErrorList('FAIL', self.failures) -
django/test/__init__.py
4 4 5 5 from django.test.client import Client 6 6 from django.test.testcases import TestCase 7 8 class SkippedTest(Exception): 9 def __init__(self, reason): 10 self.reason = reason 11 12 def __str__(self): 13 return self.reason -
django/test/decorators.py
1 from django.core import urlresolvers 2 from django.test import SkippedTest 3 4 def views_required(required_views=[]): 5 def urls_found(): 6 try: 7 for view in required_views: 8 urlresolvers.reverse(view) 9 return True 10 except urlresolvers.NoReverseMatch: 11 return False 12 reason = 'Required view%s for this test not found: %s' % \ 13 (len(required_views) > 1 and 's' or '', ', '.join(required_views)) 14 return conditional_skip(urls_found, reason=reason) 15 16 def modules_required(required_modules=[]): 17 def modules_found(): 18 try: 19 for module in required_modules: 20 __import__(module) 21 return True 22 except ImportError: 23 return False 24 reason = 'Required module%s for this test not found: %s' % \ 25 (len(required_modules) > 1 and 's' or '', ', '.join(required_modules)) 26 return conditional_skip(modules_found, reason=reason) 27 28 def skip_specific_database(database_engine): 29 def database_check(): 30 from django.conf import settings 31 return database_engine == settings.DATABASE_ENGINE 32 reason = 'Test not run for database engine %s.' % database_engine 33 return conditional_skip(database_check, reason=reason) 34 35 def conditional_skip(required_condition, reason=''): 36 if required_condition(): 37 return lambda x: x 38 else: 39 return skip_test(reason) 40 41 def skip_test(reason=''): 42 def _skip(x): 43 raise SkippedTest(reason=reason) 44 return lambda x: _skip -
django/contrib/auth/tests/views.py
5 5 from django.conf import settings 6 6 from django.contrib.auth.models import User 7 7 from django.test import TestCase 8 from django.test.decorators import views_required 8 9 from django.core import mail 10 from django.core.urlresolvers import reverse 9 11 10 12 class PasswordResetTest(TestCase): 11 13 fixtures = ['authtestdata.json'] 12 urls = 'django.contrib.auth.urls'13 14 14 15 def test_email_not_found(self): 15 16 "Error is raised if the provided email address isn't currently registered" 16 response = self.client.get( '/password_reset/')17 response = self.client.get(reverse('django.contrib.auth.views.password_reset')) 17 18 self.assertEquals(response.status_code, 200) 18 response = self.client.post( '/password_reset/', {'email': 'not_a_real_email@email.com'})19 response = self.client.post(reverse('django.contrib.auth.views.password_reset'), {'email': 'not_a_real_email@email.com'}) 19 20 self.assertContains(response, "That e-mail address doesn't have an associated user account") 20 21 self.assertEquals(len(mail.outbox), 0) 22 test_email_not_found = views_required(required_views=['django.contrib.auth.views.password_reset'])(test_email_not_found) 21 23 22 24 def test_email_found(self): 23 25 "Email is sent if a valid email address is provided for password reset" 24 response = self.client.post( '/password_reset/', {'email': 'staffmember@example.com'})26 response = self.client.post(reverse('django.contrib.auth.views.password_reset'), {'email': 'staffmember@example.com'}) 25 27 self.assertEquals(response.status_code, 302) 26 28 self.assertEquals(len(mail.outbox), 1) 27 29 self.assert_("http://" in mail.outbox[0].body) 30 test_email_found = views_required(required_views=['django.contrib.auth.views.password_reset'])(test_email_found) 28 31 29 32 def _test_confirm_start(self): 30 33 # Start by creating the email 31 response = self.client.post( '/password_reset/', {'email': 'staffmember@example.com'})34 response = self.client.post(reverse('django.contrib.auth.views.password_reset'), {'email': 'staffmember@example.com'}) 32 35 self.assertEquals(response.status_code, 302) 33 36 self.assertEquals(len(mail.outbox), 1) 34 37 return self._read_signup_email(mail.outbox[0]) … … 44 47 # redirect to a 'complete' page: 45 48 self.assertEquals(response.status_code, 200) 46 49 self.assert_("Please enter your new password" in response.content) 50 test_confirm_valid = views_required(required_views=['django.contrib.auth.views.password_reset'])(test_confirm_valid) 47 51 52 48 53 def test_confirm_invalid(self): 49 54 url, path = self._test_confirm_start() 50 55 # Lets munge the token in the path, but keep the same length, … … 54 59 response = self.client.get(path) 55 60 self.assertEquals(response.status_code, 200) 56 61 self.assert_("The password reset link was invalid" in response.content) 62 test_confirm_invalid = views_required(required_views=['django.contrib.auth.views.password_reset'])(test_confirm_invalid) 57 63 58 64 def test_confirm_invalid_post(self): 59 65 # Same as test_confirm_invalid, but trying … … 66 72 # Check the password has not been changed 67 73 u = User.objects.get(email='staffmember@example.com') 68 74 self.assert_(not u.check_password("anewpassword")) 75 test_confirm_invalid_post = views_required(required_views=['django.contrib.auth.views.password_reset'])(test_confirm_invalid_post) 69 76 70 77 def test_confirm_complete(self): 71 78 url, path = self._test_confirm_start() … … 81 88 response = self.client.get(path) 82 89 self.assertEquals(response.status_code, 200) 83 90 self.assert_("The password reset link was invalid" in response.content) 91 test_confirm_complete = views_required(required_views=['django.contrib.auth.views.password_reset'])(test_confirm_complete) 84 92 85 93 def test_confirm_different_passwords(self): 86 94 url, path = self._test_confirm_start() … … 88 96 'new_password2':' x'}) 89 97 self.assertEquals(response.status_code, 200) 90 98 self.assert_("The two password fields didn't match" in response.content) 99 test_confirm_different_passwords = views_required(required_views=['django.contrib.auth.views.password_reset'])(test_confirm_different_passwords) 91 100 92 93 101 class ChangePasswordTest(TestCase): 94 102 fixtures = ['authtestdata.json'] 95 103 urls = 'django.contrib.auth.urls' -
tests/regressiontests/test_decorators/tests.py
1 """ 2 >>> from django.test import SkippedTest 3 >>> from django.test.decorators import * 4 5 >>> skip_test()(None)(None) 6 Traceback (most recent call last): 7 ... 8 SkippedTest 9 10 >>> skip_test(reason='testing')(None)(None) 11 Traceback (most recent call last): 12 ... 13 SkippedTest: testing 14 15 >>> conditional_skip(lambda: False)(None)(None) 16 Traceback (most recent call last): 17 ... 18 SkippedTest 19 20 >>> conditional_skip(lambda: True)(lambda: True)() 21 True 22 23 """ -
docs/topics/testing.txt
865 865 This test case will use the contents of ``myapp.test_urls`` as the 866 866 URLconf for the duration of the test case. 867 867 868 Skipping tests bound to fail 869 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 870 871 **New in Django development version** 872 873 Occasionally it's helpful to specify tests that are skipped under certain 874 circumstances. To accomplish this, the Django test framework offers decorators 875 that you can apply to your test methods for them to be conditionally skipped. 876 877 You can supply your own condition function as follows:: 878 879 from django.tests.decorators import * 880 881 class TestUnderCondition(TestCase): 882 883 def _my_condition(): 884 # Condition returning True if test should be run and False if it 885 # should be skipped. 886 887 @conditional_skip(_my_condition, reason='This test should be skipped sometimes') 888 def testOnlyOnTuesday(self): 889 # Test to run if _my_condition evaluates to True 890 891 In addition, the Django test framework supplies a handful of skip conditions that 892 handle commonly used conditions for skipping tests. 893 894 ``views_required(required_views=[])`` 895 Does a ``urlresolver.Reverse`` on the required views supplied. Runs test only if 896 all views in ``required_views`` are in use. 897 898 ``modules_required(required_modules=[])`` 899 Runs tests only if all modules in ``required_modules`` can be imported. 900 901 ``skip_specific_database(database_engine)`` 902 Skips test if ``settings.DATABASE_ENGINE`` is equal to database_engine. 903 904 If a test is skipped, it is added to a skipped category in the test runner and 905 the test results are reported as such:: 906 907 ====================================================================== 908 SKIPPED: test_email_found (django.contrib.auth.tests.basic.PasswordResetTest) 909 ---------------------------------------------------------------------- 910 Traceback (most recent call last): 911 File "/Users/dnaquin/Dropbox/Sandbox/django/django/test/decorators.py", line 43, in _skip 912 raise SkippedTest(reason=reason) 913 SkippedTest: Required view for this test not found: django.contrib.auth.views.password_reset 914 915 ---------------------------------------------------------------------- 916 Ran 408 tests in 339.663s 917 918 FAILED (failures=1, skipped=2) 919 868 920 .. _emptying-test-outbox: 869 921 870 922 Emptying the test outbox