Ticket #2879: django_live_server.diff
File django_live_server.diff, 8.0 KB (added by , 16 years ago) |
---|
-
django/test/testcases.py
1 import os 2 import sys 1 3 import re 4 import socket 5 import threading 2 6 import unittest 3 7 from urlparse import urlsplit, urlunsplit 4 8 5 9 from django.http import QueryDict 6 10 from django.db import transaction 7 11 from django.core import mail 12 from django.core.handlers.wsgi import WSGIHandler 8 13 from django.core.management import call_command 14 from django.core.management.color import color_style 15 from django.core.servers.basehttp import WSGIServer, WSGIServerException, \ 16 AdminMediaHandler, WSGIRequestHandler 9 17 from django.test import _doctest as doctest 10 18 from django.test.client import Client 19 from django.test.utils import create_test_db 11 20 12 21 normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) 13 22 … … 47 56 # side effects on other tests. 48 57 transaction.rollback_unless_managed() 49 58 59 class StoppableWSGIServer(WSGIServer): 60 """ WSGIServer with short timout, so that server thread can stop this server. """ 61 62 def server_bind(self): 63 """ Sets timeout to 1 second. """ 64 WSGIServer.server_bind(self) 65 self.socket.settimeout(1) 66 67 def get_request(self): 68 """ Checks for timeout when getting request. """ 69 try: 70 sock, address = self.socket.accept() 71 sock.settimeout(None) 72 return (sock, address) 73 except socket.timeout: 74 raise 75 76 class TestServerThread(threading.Thread): 77 """ Thread for running a http server while tests are running. """ 78 def __init__(self, address, port): 79 self.address = address 80 self.port = port 81 self._stopevent = threading.Event() 82 self.started = threading.Event() 83 self.error = None 84 super(TestServerThread, self).__init__() 85 86 def run(self): 87 """ Sets up test server and database and loops over handling http requests. """ 88 try: 89 handler = AdminMediaHandler(WSGIHandler()) 90 server_address = (self.address, self.port) 91 httpd = StoppableWSGIServer(server_address, WSGIRequestHandler) 92 httpd.set_app(handler) 93 self.started.set() 94 except WSGIServerException, e: 95 # Use helpful error messages instead of ugly tracebacks. 96 self.error = e 97 self.started.set() 98 return 99 100 # Must do database stuff in this new thread if database in memory. 101 from django.conf import settings 102 if settings.DATABASE_ENGINE == "sqlite3" \ 103 and (not settings.TEST_DATABASE_NAME or settings.TEST_DATABASE_NAME == ":memory:"): 104 db_name = create_test_db(0) 105 # Import the fixture data into the test database. 106 if hasattr(self, 'fixtures'): 107 # We have to use this slightly awkward syntax due to the fact 108 # that we're using *args and **kwargs together. 109 call_command('loaddata', *self.fixtures, **{'verbosity': 0}) 110 111 # Loop until we get a stop event 112 while not self._stopevent.isSet(): 113 httpd.handle_request() 114 115 def join(self, timeout=None): 116 """ Stop the thread and wait for it to end. """ 117 self._stopevent.set() 118 threading.Thread.join(self, timeout) 119 50 120 class TestCase(unittest.TestCase): 51 121 def _pre_setup(self): 52 122 """Performs any pre-test setup. This includes: … … 79 149 result.addError(self, sys.exc_info()) 80 150 return 81 151 super(TestCase, self).__call__(result) 152 153 def start_test_server(self, address='localhost', port=8000): 154 """ 155 Creates a live test server object (instance of WSGIServer). 156 """ 157 self.server_thread = TestServerThread(address, port) 158 self.server_thread.start() 159 self.server_thread.started.wait() 160 if self.server_thread.error: 161 raise self.server_thread.error 162 163 def stop_test_server(self): 164 if self.server_thread: 165 self.server_thread.join() 82 166 83 167 def assertRedirects(self, response, expected_url, status_code=302, 84 168 target_status_code=200, host=None): -
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 import os 9 import urllib 9 10 10 11 class AssertContainsTests(TestCase): 11 12 def test_contains(self): … … 318 319 self.client.get("/test_client_regress/staff_only/") 319 320 except SuspiciousOperation: 320 321 self.fail("Staff should be able to visit this page") 322 323 class TestServerTests(TestCase): 324 def setUp(self): 325 self.start_test_server(address='localhost', port=8000) 326 327 def tearDown(self): 328 self.stop_test_server() 329 330 def test_server_up(self): 331 url = urllib.urlopen('http://localhost:8000/') 332 self.assertEqual(url.read(), 'Django Internal Tests: 404 Error') 333 url.close() 334 335 def test_serve_page(self): 336 url = urllib.urlopen('http://localhost:8000/accounts/login/') 337 # Just make sure this isn't a 404, and we've gotten something. 338 self.assertNotEqual(url.read(), 'Django Internal Tests: 404 Error') 339 url.close() -
AUTHORS
269 269 Robert Myers <myer0052@gmail.com> 270 270 Nebojša Dorđević 271 271 Doug Napoleone <doug@dougma.com> 272 Devin Naquin <devin@disqus.com> 272 273 Gopal Narayanan <gopastro@gmail.com> 273 274 Fraser Nevett <mail@nevett.org> 274 275 Sam Newman <http://www.magpiebrain.com/> -
docs/testing.txt
797 797 .. _dumpdata documentation: ../django-admin/#dumpdata-appname-appname 798 798 .. _loaddata documentation: ../django-admin/#loaddata-fixture-fixture 799 799 800 Running tests with a live test server 801 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 802 803 **New in Django development version** 804 805 When running tests that use in-browser frameworks such as Twill_ and 806 Selenium_, it's necessary to have a running test server. Django's custom ``TestCase`` class supports starting a live server for these purposes. 807 808 ``start_test_server(address='localhost', port=8000)`` 809 Starts a test server at ``address`` on ``port``. This should be done in the 810 ``setUp()`` method of a subclass of ``TestCase``. The server then can be accessed 811 at http://address:port. 812 813 ``stop_test_server()`` 814 Stops the test server that was started with ``start_test_server``. This must be 815 done before ``start_test_server`` can be called again, so this should be done in 816 the ``tearDown()`` method of a subclass of ``TestCase``. 817 818 This can be used to start a server that can then be accessed by Twill, Selenium or another in-browser test framework. For example:: 819 820 from django.test.testcases import TestCase 821 from selenium import selenium 822 823 class TestLogin(TestCase): 824 fixtures = ['login'] 825 826 def setUp(self): 827 # start test server and tell selenium where to find it 828 self.start_test_server('localhost', 8000) 829 self.selenium = selenium(addr, '4444', \ 830 '*pifirefox', 'http://localhost:8000') 831 832 def tearDown(self): 833 # stop server and selenium 834 self.selenium.stop() 835 self.stop_test_server() 836 837 def testLogin(self): 838 self.selenium.open('/admin/') 839 self.selenium.type('username','admin') 840 self.selenium.type('password','password') 841 self.selenium.click("//input[@value='Log in']") 842 843 .. _Twill: http://twill.idyll.org/ 844 .. _Selenium: http://www.openqa.org/selenium/ 845 800 846 Emptying the test outbox 801 847 ~~~~~~~~~~~~~~~~~~~~~~~~ 802 848