Reputation: 794
I want to test my application
I have these two files (Not my real application but this presents the same problem).
File 1: testServer.py
import SocketServer
import SimpleHTTPServer
class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
f = self.wfile
self.send_response(200)
self.end_headers()
f.write("ok")
def runServer(port):
Handler = ServerHandler
httpd = SocketServer.TCPServer(("", port), Handler)
httpd.serve_forever()
if __name__ == "__main__":
runServer(8000)
File 2: test_testServer.py
import testServer
from multiprocessing import Process
import httplib
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.serverProcess = Process(target = testServer.runServer, args = (8000,))
cls.serverProcess.daemon = True
cls.serverProcess.start()
@classmethod
def tearDownClass(cls):
cls.serverProcess.terminate()
def test_Server(self):
conn = httplib.HTTPConnection("localhost", 8000)
conn.request("GET", "")
response = conn.getresponse().read()
self.assertTrue(response, "ok")
if __name__ == "__main__":
unittest.main()
So my goal is to start the server I coded in a process and then test its replies to different requests.
When I launch the test alone, it works perfectly fine:
C:\Users\r.bunel\workspace\Sandbox>python test_testServer.py
127.0.0.1 - - [23/Dec/2013 09:23:50] "GET / HTTP/1.1" 200 -
----------------------------------------------------------------------
Ran 1 test in 1.009s
OK
But if I start it as a part of my all test suite, by using unittest's discover, it doesn't work:
C:\Users\r.bunel\workspace\Sandbox>python -m unittest discover
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Python27\lib\multiprocessing\forking.py", line 380, in main
prepare(preparation_data)
File "C:\Python27\lib\multiprocessing\forking.py", line 488, in prepare
assert main_name not in sys.modules, main_name
AssertionError: __main__
E
======================================================================
ERROR: test_Server (test_testServer.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\r.bunel\workspace\Sandbox\test_testServer.py", line 22, in test_Server
conn.request("GET", "")
File "C:\Python27\lib\httplib.py", line 973, in request
self._send_request(method, url, body, headers)
File "C:\Python27\lib\httplib.py", line 1007, in _send_request
self.endheaders(body)
File "C:\Python27\lib\httplib.py", line 969, in endheaders
self._send_output(message_body)
File "C:\Python27\lib\httplib.py", line 829, in _send_output
self.send(msg)
File "C:\Python27\lib\httplib.py", line 791, in send
self.connect()
File "C:\Python27\lib\httplib.py", line 772, in connect
self.timeout, self.source_address)
File "C:\Python27\lib\socket.py", line 571, in create_connection
raise err
error: [Errno 10061] Aucune connexion nÆa pu Ûtre Útablie car lÆordinateur cible lÆa expressÚment refusÚe
----------------------------------------------------------------------
Ran 1 test in 2.009s
FAILED (errors=1)
So, my question is whether or not there is a reason for unittest to behave this way and what are my options to make these tests work inside unittest?
Upvotes: 1
Views: 348
Reputation: 794
Ok, after realising with the help of @Alo Sarv that the problem lied in the multiprocessing module, I found a solution.
Here it is in case someone encounters the same problem:
file 1:testServer.py
import SocketServer
import SimpleHTTPServer
class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
f = self.wfile
self.send_response(200)
self.end_headers()
f.write("ok")
def runServer(port):
Handler = ServerHandler
httpd = SocketServer.TCPServer(("", port), Handler)
httpd.serve_forever()
if __name__ == "__main__":
runServer(8000)
file 2: test_testServer.py
from testServer import ServerHandler
import SocketServer
from threading import Thread
import httplib
import unittest
class serverThread(Thread):
def __init__(self, port):
self.Handler = ServerHandler
self.httpd = SocketServer.TCPServer(("", port), self.Handler)
Thread.__init__(self)
def run(self):
self.httpd.serve_forever()
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.serverThread = serverThread(8000)
cls.serverThread.daemon = True
cls.serverThread.start()
@classmethod
def tearDownClass(cls):
cls.serverThread.httpd.__shutdown_request = True
def test_Server(self):
conn = httplib.HTTPConnection("localhost", 8000)
conn.request("GET", "")
response = conn.getresponse().read()
self.assertTrue(response, "ok")
if __name__ == "__main__":
unittest.main()
In short, the solution was to replace the use of multiprocessing by the use of threads. Then, adapting the server in order to be able to stop the thread properly (because thread can not be killed as easily as Process)
Upvotes: 1
Reputation: 376
Perhaps the unittest is trying to connect to the server before it has had time to start up properly in the second thread? Try adding time.sleep(1)
after cls.serverProcess.start()
in setupClass(cls)
?
@classmethod
def setUpClass(cls):
cls.serverProcess = Process(target = testServer.runServer, args = (8000,))
cls.serverProcess.daemon = True
cls.serverProcess.start()
time.sleep(1)
Upvotes: 1