使用SimpleHTTPServer进行单元测试

18 投票
3 回答
6292 浏览
提问于 2025-04-15 17:30

我正在写一个Python模块,用来封装某个网络服务的API。这个API是REST类型的,所以实现起来相对简单。

不过,在进行单元测试的时候我遇到了一个问题:因为我并不运行这个模块所针对的服务,所以我不想频繁地去请求它们,但同时我又需要获取一些数据来进行测试。我考虑过使用SimpleHTTPServer,这个方法还不错。

我解决了部分问题,但现在由于我似乎无法终止线程,每次多次启动测试应用时都会出现“地址已被使用”的问题。

以下是一些示例代码:

PORT = 8001

handler = SimpleHTTPServer.SimpleHTTPRequestHandler

httpd = SocketServer.TCPServer(("", PORT), handler)

httpd_thread = threading.Thread(target=httpd.serve_forever)
httpd_thread.daemon = True
httpd_thread.start()

api_data = urllib.urlopen("http://localhost:8001/post/index.json")
print "Data start:"
print json.load(api_data)

这里的“index.json”是我制作的一个模拟JSON文件,用来替代真实的文件。请问我该如何在程序结束后优雅地清理这些东西呢?

3 个回答

4

我们使用的是一个基于 wsgiref 的服务器。http://docs.python.org/library/wsgiref.html

在这个服务器上添加新功能非常简单,尤其是在我们添加单元测试的时候。

我们通过 subprocess 来启动这个服务器。http://docs.python.org/library/subprocess.html?highlight=subprocess#module-subprocess

我们在这种测试中不使用线程。为什么呢?(1)我们的单元测试服务器比较复杂,我们希望它和客户端应用程序完全隔离开来。(2)我们的客户端应用程序会在不同的硬件上作为独立的进程运行,我们需要确保对这种配置有合理的性能预期。(3)这样做更简单。(4)在所有平台上都能使用。(5)从独立的单元测试切换到像生产环境一样的集成测试也非常简单,因为服务器已经在运行了。

实际上,我们有一个小的 WSGI 应用程序,可以让服务器以相对可控的方式关闭,这样日志也能正常关闭。

5

这个帖子虽然旧了,但这里的回答对我没什么帮助。我在用HTTPServer,每次单元测试后都会关闭它(默认情况下,HTTPServer的allow_reuse_address设置为1)。不过在调用关闭后,我还是遇到了“地址已经在使用”的问题。我是通过下面的方式解决的:

from BaseHTTPServer import HTTPServer

class MyHTTPServer(HTTPServer):
    def shutdown(self):
        self.socket.close()
        HTTPServer.shutdown(self)

我不太明白为什么默认情况下不会这样?这可能不是最优的做法吗?

12

试着使用一个TCPServer的子类,并把allow_reuse_address设置为True,这样可以允许地址重用。

import socketserver

class TestServer(socketserver.TCPServer):
    allow_reuse_address = True

...
httpd = TestServer(("", PORT), handler)

撰写回答