Ticket #2879: django_live_server_r8458.diff
File django_live_server_r8458.diff, 8.9 KB (added by , 16 years ago) |
---|
-
django/test/testcases.py
1 1 import re 2 2 import unittest 3 import socket 4 import threading 3 5 from urlparse import urlsplit, urlunsplit 4 6 from xml.dom.minidom import parseString, Node 5 7 … … 12 14 from django.test import _doctest as doctest 13 15 from django.test.client import Client 14 16 from django.utils import simplejson 17 from django.core.handlers.wsgi import WSGIHandler 18 from django.core.servers import basehttp 15 19 16 20 normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) 17 21 … … 169 173 # side effects on other tests. 170 174 transaction.rollback_unless_managed() 171 175 176 class 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 172 221 class TestCase(unittest.TestCase): 173 222 def _pre_setup(self): 174 223 """Performs any pre-test setup. This includes: … … 225 274 settings.ROOT_URLCONF = self._old_root_urlconf 226 275 clear_url_caches() 227 276 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 228 289 def assertRedirects(self, response, expected_url, status_code=302, 229 290 target_status_code=200, host=None): 230 291 """Asserts that a response redirected to a specific URL, and that the -
django/core/servers/basehttp.py
11 11 import mimetypes 12 12 import os 13 13 import re 14 import socket 14 15 import sys 15 16 import urllib 16 17 … … 658 659 start_response(status, headers.items()) 659 660 return output 660 661 662 class 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 661 679 def run(addr, port, wsgi_handler): 662 680 server_address = (addr, port) 663 681 httpd = WSGIServer(server_address, WSGIRequestHandler) -
tests/regressiontests/test_client_regress/models.py
6 6 from django.core.urlresolvers import reverse 7 7 from django.core.exceptions import SuspiciousOperation 8 8 9 import urllib 10 9 11 class AssertContainsTests(TestCase): 10 12 def test_contains(self): 11 13 "Responses can be inspected for content, including counting repeated substrings" … … 326 328 url = reverse('arg_view', args=['somename']) 327 329 self.assertEquals(url, '/test_client_regress/arg_view/somename/') 328 330 331 class 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 329 349 class SessionTests(TestCase): 330 350 fixtures = ['testdata.json'] 331 351 … … 354 374 response = self.client.get('/test_client_regress/check_session/') 355 375 self.assertEqual(response.status_code, 200) 356 376 self.assertEqual(response.content, 'YES') 357 358 No newline at end of file 377 -
AUTHORS
290 290 Robert Myers <myer0052@gmail.com> 291 291 Nebojša Dorđević 292 292 Doug Napoleone <doug@dougma.com> 293 Devin Naquin <dnaquin@gmail.com> 293 294 Gopal Narayanan <gopastro@gmail.com> 294 295 Fraser Nevett <mail@nevett.org> 295 296 Sam Newman <http://www.magpiebrain.com/> -
docs/testing.txt
823 823 This test case will use the contents of ``myapp.test_urls`` as the 824 824 URLconf for the duration of the test case. 825 825 826 Running tests with a live test server 827 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 828 829 **New in Django development version** 830 831 When running tests that use in-browser frameworks such as Twille_ and 832 Selenium_, 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 845 This can be used to start a server that can then be accessed by Twill, Selenium 846 or 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 826 874 Emptying the test outbox 827 875 ~~~~~~~~~~~~~~~~~~~~~~~~ 828 876