使用 SimpleHTTPServer 进行单元测试

Posted

技术标签:

【中文标题】使用 SimpleHTTPServer 进行单元测试【英文标题】:Using SimpleHTTPServer for unit testing 【发布时间】:2010-12-31 09:48:33 【问题描述】:

我正在编写一个 Python 模块,它封装了某个 Web 服务 API。这都是 REST,因此实现起来相对简单。

但是,在单元测试方面我发现了一个问题:由于我不运行我为此模块创建的服务,我不想锤击它们,但同时我需要检索数据运行我的测试。我看了SimpleHTTPServer,没问题。

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

这里有一些示例代码

PORT = 8001

handler = SimpleHTTPServer.SimpleHTTPRequestHandler

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

httpd_thread = threading.Thread(target=httpd.serve_forever)
httpd_thread.setDaemon(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 文件,它替代了真实的东西。程序终止后如何优雅地清理东西?

【问题讨论】:

SimpleHTTPServer 应该是最简单的方法。你遇到了什么问题? 我改写了一些东西,希望现在更清楚了。 【参考方案1】:

旧线程,但这里的答案对我没有帮助,我正在使用 HTTPServer,并在每次单元测试后关闭(默认情况下 HTTPServer 设置了 allow_reuse_address = 1)。但是在调用关机后我仍然得到地址已经在使用的问题。我固定使用:

from BaseHTTPServer import HTTPServer

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

不确定为什么默认情况下不会发生这种情况?这可能不是最优的吗?

【讨论】:

虽然这对我有用,因为它避免了当我尝试在测试中打开我的 URL 时的地址重用问题,我最终得到:select error (9, 'Bad file descriptor') when关闭服务器。尽管我的测试似乎确实有效,但仍在寻找不会产生此异常的解决方案。 Python 2.7.10。【参考方案2】:

尝试使用subclass of TCPServer with allow_reuse_address set True:

class TestServer(SocketServer.TCPServer):
    allow_reuse_address = True

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

【讨论】:

太棒了!又好又简单 这对我不起作用,但我能够通过在 setUpClass 方法而不是 setUp 方法中设置 SocketServer 来解决这个问题。 address in use 错误似乎在第二次调用 setUp 方法时发生(在运行第二次测试时发生)。【参考方案3】:

我们使用基于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 应用程序,它以合理控制的方式关闭服务器,以便正确关闭日志。

【讨论】:

确实,似乎 subprocess 可能是一个不错的选择。将进一步调查。

以上是关于使用 SimpleHTTPServer 进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

使用 SimpleHTTPServer 禁用索引文件

BaseHTTPServer和SimpleHTTPServer有什么区别?何时何地使用它们?

Python SimpleHTTPServer

单测方法论---1

我可以用 python 的 SimpleHTTPServer 设置一个标题吗?

单元测试集成测试