Python:基于socket的代码单元测试?

2024-09-28 20:51:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个Python客户机+服务器,它使用gevent.socket进行通信。有没有测试代码的套接字级别操作的好方法(例如,验证带有无效证书的SSL连接是否会被拒绝)?或者仅仅是spawn一个真正的服务器是最简单的吗?

编辑:由于涉及到复杂的交互,我认为“天真”的模拟不足以测试SSL组件。我错了吗?或者有更好的方法来测试SSL的东西吗?


Tags: 方法服务器编辑ssl客户机组件geventsocket
3条回答

还有一种(我认为更好的)方法:你应该模拟你正在使用的库。 python的模拟助手示例是mox

您不需要一组具有有效证书的服务器、另一组具有无效证书的服务器、完全不支持ssl的服务器、完全不响应任何数据包的服务器等等。您可以使用“虚拟”客户端套接字模拟它们的行为。它与Mox一起工作的方式是,首先“教导”它应该期望什么以及它应该如何反应,然后在将真实的gevent.socket替换为模拟的gevent.socket时,在上面执行真正的代码。要掌握诀窍需要一些练习,但这是值得的。

模拟和存根是很好的,但有时您需要将其提升到下一个集成级别。由于生成一个服务器(甚至是一个fakeish服务器)可能需要一些时间,因此可以考虑使用一个单独的测试套件(称为集成测试)。

“像使用它一样测试它”是我的指导原则,如果你的模拟和存根太多,以至于你的测试变得微不足道,那就没那么有用了(尽管几乎任何测试都比没有好)。如果您关心处理坏的SSL证书,那么一定要做一些坏的证书,并编写一个测试夹具,您可以将它们提供给。如果这意味着产生一个服务器,那么就这样吧。如果这个bug足够多的话,可能会导致重构,从而使它可以以另一种方式进行测试。

您可以轻松地启动服务器,然后在测试用例中访问它。gevent的own test suite正是为了测试gevent的built-in servers

例如:

class SimpleServer(gevent.server.StreamServer):

    def handle(self, socket, address):
        socket.sendall('hello and goodbye!')

class Test(unittest.TestCase):      

    def test(self):
        server = SimpleServer(('127.0.0.1', 0))
        server.start()
        client = gevent.socket.create_connection(('127.0.0.1', server.server_port))
        response = client.makefile().read()
        assert response == 'hello and goodbye!'
        server.stop()

使用0作为端口值意味着服务器将使用任何可用的端口。启动服务器后,bind选择的实际值可用作server_port属性。

StreamServer也支持SSL,将keyfilecertfile参数传递给构造函数,它将在传递给处理程序之前用SSLObject包装每个套接字。

如果您不使用StreamServer,并且您的服务器基于Greenlet,那么实际上spawning应该这样做。不要忘记在测试用例结束时kill它。

gevent中启动服务器和生成greenlet是快速操作,比创建新线程或进程快得多,而且您可以轻松地为每个测试用例创建新服务器。只要你不再需要服务器就别忘了清理。

我相信不需要模拟任何gevent API,因为服务器和客户机可以在同一个进程中愉快地生活,所以使用它要容易得多。

相关问题 更多 >