Django

Code

Changeset 5150

Show
Ignore:
Timestamp:
05/04/07 22:03:33 (2 years ago)
Author:
russellm
Message:

Added a default test Client to TestCase?, and added some assertions for some common testing patterns.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/test/testcases.py

    r4659 r5150  
    11import re, doctest, unittest 
     2from urlparse import urlparse 
    23from django.db import transaction 
    34from django.core import management 
    45from django.db.models import get_apps 
    5      
     6from django.test.client import Client 
     7 
    68normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) 
    79 
     
    4749         
    4850        """ 
     51        self.client = Client() 
    4952        self.install_fixtures() 
    5053        super(TestCase, self).run(result) 
     54 
     55    def assertRedirects(self, response, expected_path): 
     56        """Assert that a response redirected to a specific URL, and that the  
     57        redirect URL can be loaded. 
     58         
     59        """ 
     60        self.assertEqual(response.status_code, 302,  
     61            "Response didn't redirect: Reponse code was %d" % response.status_code) 
     62        scheme, netloc, path, params, query, fragment = urlparse(response['Location']) 
     63        self.assertEqual(path, expected_path,  
     64            "Response redirected to '%s', expected '%s'" % (path, expected_path)) 
     65        redirect_response = self.client.get(path) 
     66        self.assertEqual(redirect_response.status_code, 200,  
     67            "Couldn't retrieve redirection page '%s'" % path) 
     68     
     69    def assertContains(self, response, text, count=1): 
     70        """Assert that a response indicates that a page was retreived successfully, 
     71        (i.e., the HTTP status code was 200), and that ``text`` occurs ``count``  
     72        times in the content of the response. 
     73         
     74        """ 
     75        self.assertEqual(response.status_code, 200, 
     76            "Couldn't retrieve page'") 
     77        real_count = response.content.count(text) 
     78        self.assertEqual(real_count, count, 
     79            "Could only find %d of %d instances of '%s' in response" % (real_count, count, text)) 
     80             
  • django/trunk/docs/testing.txt

    r5040 r5150  
    167167 
    168168* `Test Client`_ 
    169 * Fixtures
     169* `TestCase`
    170170 
    171171Test Client 
     
    358358            self.failUnlessEqual(len(response.context['customers']), 5) 
    359359 
    360 Fixtures 
     360TestCase 
    361361-------- 
     362 
     363Normal python unit tests extend a base class of ``unittest.testCase``.  
     364Django provides an extension of this base class - ``django.test.TestCase``  
     365- that provides some additional capabilities that can be useful for  
     366testing web sites.  
     367 
     368Moving from a normal unittest TestCase to a Django TestCase is easy - just 
     369change the base class of your test from ``unittest.TestCase`` to  
     370``django.test.TestCase``. All of the standard Python unit test facilities 
     371will continue to be available, but they will be augmented with some useful 
     372extra facilities. 
     373 
     374Default Test Client 
     375~~~~~~~~~~~~~~~~~~~ 
     376** New in Django development version ** 
     377 
     378Every test case in a ``django.test.TestCase`` instance has access to an 
     379instance of a Django `Test Client`_. This Client can be accessed as  
     380``self.client``. This client is recreated for each test. 
     381 
     382Fixture loading 
     383~~~~~~~~~~~~~~~ 
    362384 
    363385A test case for a database-backed website isn't much use if there isn't any 
     
    377399    data (such as a default set of categories). Fixtures with other names 
    378400    can be installed manually using ``django-admin.py loaddata``.  
    379      
    380401 
    381402However, for the purposes of unit testing, each test must be able to  
    382403guarantee the contents of the database at the start of each and every 
    383 test. To do this, Django provides a TestCase baseclass that can integrate 
    384 with fixtures. 
    385  
    386 Moving from a normal unittest TestCase to a Django TestCase is easy - just 
    387 change the base class of your test, and define a list of fixtures 
    388 to be used. For example, the test case from `Writing unittests`_ would  
     404test.  
     405 
     406To define a fixture for a test, all you need to do is add a class 
     407attribute to your test describing the fixtures you want the test to use. 
     408For example, the test case from `Writing unittests`_ would  
    389409look like:: 
    390410 
     
    411431another test, or the order of test execution. 
    412432 
     433Assertions 
     434~~~~~~~~~~ 
     435** New in Django development version ** 
     436 
     437Normal Python unit tests have a wide range of assertions, such as  
     438``assertTrue`` and ``assertEquals`` that can be used to validate behavior.  
     439``django.TestCase`` adds to these, providing some assertions 
     440that can be useful in testing the behavior of web sites. 
     441 
     442``assertRedirects(response, expected_path)`` 
     443    Assert that the response received redirects the browser to the provided 
     444    path, and that the expected_path can be retrieved. 
     445 
     446``assertContains(response, text, count=1)`` 
     447    Assert that a response indicates that a page was retreived successfully, 
     448    (i.e., the HTTP status code was 200), and that ``text`` occurs ``count``  
     449    times in the content of the response. 
     450     
    413451Running tests 
    414452============= 
  • django/trunk/tests/modeltests/test_client/models.py

    r4796 r5150  
    2525    fixtures = ['testdata.json'] 
    2626     
    27     def setUp(self): 
    28         "Set up test environment" 
    29         self.client = Client() 
    30          
    3127    def test_get_view(self): 
    3228        "GET a view" 
     
    3430         
    3531        # Check some response details 
    36         self.assertEqual(response.status_code, 200
     32        self.assertContains(response, 'This is a test'
    3733        self.assertEqual(response.context['var'], 42) 
    3834        self.assertEqual(response.template.name, 'GET Template') 
    39         self.failUnless('This is a test.' in response.content) 
    4035 
    4136    def test_get_post_view(self): 
     
    8176         
    8277        # Check that the response was a 302 (redirect) 
    83         self.assertEqual(response.status_code, 302
     78        self.assertRedirects(response, '/test_client/get_view/'
    8479 
    8580    def test_valid_form(self): 
     
    10398        } 
    10499        response = self.client.post('/test_client/form_view/', post_data) 
    105         self.assertEqual(response.status_code, 200
     100        self.assertContains(response, 'This field is required', 3
    106101        self.assertEqual(response.template.name, "Invalid POST Template") 
    107102 
     
    131126        # Get the page without logging in. Should result in 302. 
    132127        response = self.client.get('/test_client/login_protected_view/') 
    133         self.assertEqual(response.status_code, 302
     128        self.assertRedirects(response, '/accounts/login/'
    134129         
    135130        # Request a page that requires a login