Ticket #2879: django_live_server_r8458.diff

File django_live_server_r8458.diff, 8.9 KB (added by robertrv, 7 years ago)

Updated devin's patch with last changes in testing environment

  • django/test/testcases.py

     
    11import re
    22import unittest
     3import socket
     4import threading
    35from urlparse import urlsplit, urlunsplit
    46from xml.dom.minidom import parseString, Node
    57
     
    1214from django.test import _doctest as doctest
    1315from django.test.client import Client
    1416from django.utils import simplejson
     17from django.core.handlers.wsgi import WSGIHandler
     18from django.core.servers import basehttp
    1519
    1620normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
    1721
     
    169173        # side effects on other tests.
    170174        transaction.rollback_unless_managed()
    171175
     176class TestServerThread(threading.Thread):
     177    """Thread for running a http server while tests are running."""
     178
     179    def __init__(self, address, port):
     180        self.address = address
     181        self.port = port
     182        self._stopevent = threading.Event()
     183        self.started = threading.Event()
     184        self.error = None
     185        super(TestServerThread, self).__init__()
     186
     187    def run(self):
     188        """Sets up test server and database and loops over handling http requests."""
     189        try:
     190            handler = basehttp.AdminMediaHandler(WSGIHandler())
     191            server_address = (self.address, self.port)
     192            httpd = basehttp.StoppableWSGIServer(server_address, basehttp.WSGIRequestHandler)
     193            httpd.set_app(handler)
     194            self.started.set()
     195        except basehttp.WSGIServerException, e:
     196            self.error = e
     197            self.started.set()
     198            return
     199
     200        # Must do database stuff in this new thread if database in memory.
     201        from django.conf import settings
     202        if settings.DATABASE_ENGINE == 'sqlite3' \
     203            and (not settings.TEST_DATABASE_NAME or settings.TEST_DATABASE_NAME == ':memory:'):
     204            from django.db import connection
     205            db_name = connection.creation.create_test_db(0)
     206            # Import the fixture data into the test database.
     207            if hasattr(self, 'fixtures'):
     208                # We have to use this slightly awkward syntax due to the fact
     209                # that we're using *args and **kwargs together.
     210                call_command('loaddata', *self.fixtures, **{'verbosity': 0})
     211
     212        # Loop until we get a stop event.
     213        while not self._stopevent.isSet():
     214            httpd.handle_request()
     215
     216    def join(self, timeout=None):
     217        """Stop the thread and wait for it to finish."""
     218        self._stopevent.set()
     219        threading.Thread.join(self, timeout)
     220
    172221class TestCase(unittest.TestCase):
    173222    def _pre_setup(self):
    174223        """Performs any pre-test setup. This includes:
     
    225274            settings.ROOT_URLCONF = self._old_root_urlconf
    226275            clear_url_caches()
    227276
     277    def start_test_server(self, address='localhost', port=8000):
     278        """Creates a live test server object (instance of WSGIServer)."""
     279        self.server_thread = TestServerThread(address, port)
     280        self.server_thread.start()
     281        self.server_thread.started.wait()
     282        if self.server_thread.error:
     283            raise self.server_thread.error
     284
     285    def stop_test_server(self):
     286        if self.server_thread:
     287            self.server_thread.join()
     288
    228289    def assertRedirects(self, response, expected_url, status_code=302,
    229290                        target_status_code=200, host=None):
    230291        """Asserts that a response redirected to a specific URL, and that the
  • django/core/servers/basehttp.py

     
    1111import mimetypes
    1212import os
    1313import re
     14import socket
    1415import sys
    1516import urllib
    1617
     
    658659        start_response(status, headers.items())
    659660        return output
    660661
     662class StoppableWSGIServer(WSGIServer):
     663    """WSGIServer with short timeout, so that server thread can stop this server."""
     664
     665    def server_bind(self):
     666        """Sets timeout to 1 second."""
     667        WSGIServer.server_bind(self)
     668        self.socket.settimeout(1)
     669
     670    def get_request(self):
     671        """Checks for timeout when getting request."""
     672        try:
     673            sock, address = self.socket.accept()
     674            sock.settimeout(None)
     675            return (sock, address)
     676        except socket.timeout:
     677            raise
     678
    661679def run(addr, port, wsgi_handler):
    662680    server_address = (addr, port)
    663681    httpd = WSGIServer(server_address, WSGIRequestHandler)
  • tests/regressiontests/test_client_regress/models.py

     
    66from django.core.urlresolvers import reverse
    77from django.core.exceptions import SuspiciousOperation
    88
     9import urllib
     10
    911class AssertContainsTests(TestCase):
    1012    def test_contains(self):
    1113        "Responses can be inspected for content, including counting repeated substrings"
     
    326328        url = reverse('arg_view', args=['somename'])
    327329        self.assertEquals(url, '/test_client_regress/arg_view/somename/')
    328330
     331class TestServerTests(TestCase):
     332     def setUp(self):
     333         self.start_test_server(address='localhost', port=8001)
     334 
     335     def tearDown(self):
     336         self.stop_test_server()
     337 
     338     def test_server_up(self):
     339         url = urllib.urlopen('http://localhost:8001')
     340         self.assertEqual(url.read(), 'Django Internal Tests: 404 Error')
     341         url.close()
     342 
     343     def test_serve_page(self):
     344         url = urllib.urlopen('http://localhost:8001/accounts/login')
     345         # Just make sure this isn't a 404, and we've gotten something.
     346         self.assertNotEqual(url.read(), 'Django Internal Tests: 404 Error')
     347         url.close()
     348
    329349class SessionTests(TestCase):
    330350    fixtures = ['testdata.json']
    331351
     
    354374        response = self.client.get('/test_client_regress/check_session/')
    355375        self.assertEqual(response.status_code, 200)
    356376        self.assertEqual(response.content, 'YES')
    357        
    358  No newline at end of file
     377       
  • AUTHORS

     
    290290    Robert Myers <myer0052@gmail.com>
    291291    Nebojša Dorđević
    292292    Doug Napoleone <doug@dougma.com>
     293    Devin Naquin <dnaquin@gmail.com>
    293294    Gopal Narayanan <gopastro@gmail.com>
    294295    Fraser Nevett <mail@nevett.org>
    295296    Sam Newman <http://www.magpiebrain.com/>
  • docs/testing.txt

     
    823823This test case will use the contents of ``myapp.test_urls`` as the
    824824URLconf for the duration of the test case.
    825825
     826Running tests with a live test server
     827~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     828
     829**New in Django development version**
     830
     831When running tests that use in-browser frameworks such as Twille_ and
     832Selenium_, it's necessary to have a running test server. Django's custom
     833``TestCase`` class supports starting a live server for these purposes.
     834
     835``start_test_server(address='localhost', port=8000)``
     836    Starts a test server at ``address`` on ``port``. This should be done in the
     837    ``setUp()`` method of a subclass of ``TestCase``. The server then can be
     838    accessed at http://address:port.
     839
     840``stop_test_server()``
     841    Stops the test server that was started with ``start_test_server``. This
     842    must be done before ``start_test_server`` can be called again, so this
     843    should be done in the ``tearDown()`` method of a subclass of ``TestCase``.
     844
     845This can be used to start a server that can then be accessed by Twill, Selenium
     846or another in-browser test framework. For example::
     847
     848        from django.test.testcases import TestCase
     849        from selenium import selenium
     850       
     851        class TestLogin(TestCase):
     852            fixtures = ['login_info.xml']
     853
     854            def setUp(self):
     855                # Start a test server and tell selenium where to find it.
     856                self.start_test_server('localhost', 8000)
     857                self.selenium = selenium('localhost', 4444, \
     858                        '*pifirefox', 'http://localhost:8000')
     859
     860            def tearDown(self):
     861                # Stop server and Selenium
     862                self.selenium.stop()
     863                self.stop_test_server()
     864
     865            def testLogin(self):
     866                self.selenium.open('/admin/')
     867                self.selenium.type('username', 'admin')
     868                self.selenium.type('password', 'password')
     869                self.selenium.click("//input[@value='Log in']")
     870
     871.. _Twill: http://twill.idyll.org/
     872.. _Selenium: http://www.openqa.org/selenium/
     873
    826874Emptying the test outbox
    827875~~~~~~~~~~~~~~~~~~~~~~~~
    828876
Back to Top