单独启动时的测试工作与使用unittest不同

时间:2013-12-23 08:29:01

标签: python process python-unittest

我想测试我的应用程序

我有这两个文件(不是我真正的应用程序,但这会出现同样的问题)。

文件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)

文件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()

所以我的目标是启动我在一个进程中编码的服务器,然后测试它对不同请求的回复。

当我单独启动测试时,它完全正常:

 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

但是,如果我将其作为我所有测试套件的一部分启动,通过使用unittest的发现,它不起作用:

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)

所以,我的问题是单元测试是否有理由以这种方式运行,我有什么选择让这些测试在单元测试中运行?

2 个答案:

答案 0 :(得分:1)

也许单元测试是在第二个线程中有时间正确启动之前尝试连接服务器?尝试在time.sleep(1)cls.serverProcess.start()之后添加setupClass(cls)

@classmethod
def setUpClass(cls):
    cls.serverProcess = Process(target = testServer.runServer, args = (8000,))
    cls.serverProcess.daemon = True
    cls.serverProcess.start()
    time.sleep(1)

答案 1 :(得分:1)

好的,在@Alo Sarv的帮助下意识到问题出现在多处理模块中后,我找到了一个解决方案。

这是以防有人遇到同样的问题:

文件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)

文件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()

简而言之,解决方案是使用线程替换多处理的使用。然后,调整服务器以便能够正确地停止线程(因为线程不能像进程一样容易被杀死)