| 1 | import unittest, thread, sys |
| 2 | from django.core.servers.basehttp import WSGIServer, AdminMediaHandler, WSGIServerException, WSGIRequestHandler |
| 3 | from django.core.handlers.wsgi import WSGIHandler |
| 4 | from django.conf import settings |
| 5 | from django.core.management import get_version, style |
| 6 | |
| 7 | ADDR = 'localhost' |
| 8 | PORT = 8888 |
| 9 | TEST_SERVER_FAIL = 'Test server failed to start' |
| 10 | |
| 11 | class WSGIServerWrapper(WSGIServer): |
| 12 | """ |
| 13 | Wrapper for WSGIServer. |
| 14 | |
| 15 | This is required for some added exception handling and to ignore an annoying unhandled |
| 16 | exception when calling server_close() after serve_forever() has been called in a thread. |
| 17 | """ |
| 18 | def serve_forever(self): |
| 19 | try: |
| 20 | WSGIServer.serve_forever(self) |
| 21 | except WSGIServerException, e: |
| 22 | # Use helpful error messages instead of ugly tracebacks. |
| 23 | ERRORS = { |
| 24 | 13: "You don't have permission to access that port.", |
| 25 | 98: "That port is already in use.", |
| 26 | 99: "That IP address can't be assigned-to.", |
| 27 | } |
| 28 | try: |
| 29 | error_text = ERRORS[e.args[0].args[0]] |
| 30 | except (AttributeError, KeyError): |
| 31 | error_text = str(e) |
| 32 | self.error = "Error: %s" % error_text |
| 33 | except: |
| 34 | # This is a hacky way of dealing with the error received when the exception is triggered |
| 35 | # from the server.server_close(). Because of this hack we must make sure the server came up |
| 36 | # after calling serve_forever() |
| 37 | pass |
| 38 | |
| 39 | |
| 40 | def create_test_server(addr, port): |
| 41 | """ |
| 42 | Method to create and return the test server object (instance of WSGIServerWrapper) |
| 43 | """ |
| 44 | print "\nDjango version %s, on %r:%r" % (get_version(), ADDR, PORT) |
| 45 | |
| 46 | import django |
| 47 | path = django.__path__[0] + '/contrib/admin/media' |
| 48 | handler = AdminMediaHandler(WSGIHandler(), media_dir=path) |
| 49 | server_address = (addr, port) |
| 50 | httpd = WSGIServerWrapper(server_address, WSGIRequestHandler) |
| 51 | httpd.set_app(handler) |
| 52 | |
| 53 | return httpd |
| 54 | |
| 55 | |
| 56 | class HttpTestCase(unittest.TestCase): |
| 57 | """ |
| 58 | HTTPTestCase is intended to be used for live HTTP testing of your django applications |
| 59 | using the django test server. |
| 60 | """ |
| 61 | |
| 62 | def setUp(self): |
| 63 | # Setup server for test run and assign it to self |
| 64 | self.server = create_test_server(ADDR, PORT) |
| 65 | self.server_thread_id = thread.start_new_thread(self.server.serve_forever, ()) |
| 66 | |
| 67 | print 'end of test' |
| 68 | |
| 69 | # Test that the server is up since we ignore any exceptions -- see above. |
| 70 | import socket |
| 71 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 72 | try: |
| 73 | s.connect((ADDR, PORT)) |
| 74 | s.close() |
| 75 | except: |
| 76 | if hasattr(self.server, 'error'): |
| 77 | sys.stderr.write(style(self.server.error) + '\n') |
| 78 | else: |
| 79 | raise TEST_SERVER_FAIL |
| 80 | |
| 81 | |
| 82 | def tearDown(self): |
| 83 | #Kill the server |
| 84 | self.server.server_close() |
| 85 | No newline at end of file |