20

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

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

4

3 回答 3

18

您可以轻松启动服务器,然后在测试用例中访问它。gevent自己的测试套件完全可以测试 gevent 的内置服务器

例如:

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,将keyfile参数传递certfile给构造函数,它会在将每个套接字SSLObject传递给您的处理程序之前对其进行包装。

如果您不使用StreamServer并且您的服务器是基于Greenlet的,那么确实生成它是您应该做的。不要忘记在测试用例结束时将其杀死。

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

我相信没有必要模拟任何 gevent API,使用它更容易,因为服务器和客户端可以愉快地生活在同一个进程中。

于 2010-10-29T04:45:00.883 回答
9

模拟和存根很棒,但有时您需要将其提升到下一个集成级别。由于生成服务器,即使是伪造的服务器,也可能需要一些时间,考虑一个单独的测试套件(称为集成测试)可能是合适的。

“像你将要使用它一样测试它”是我的指导方针,如果你模拟和存根太多以至于你的测试变得微不足道,那么它就没有那么有用(尽管几乎任何测试都比没有好)。如果您担心处理不好的 SSL 证书,请务必制作一些不好的证书并编写一个测试夹具,您可以将它们提供给它们。如果这意味着产生一个服务器,那就这样吧。也许如果这对您造成了足够的困扰,它将导致重构,从而使其可通过另一种方式进行测试。

于 2010-10-29T01:06:25.400 回答
8

还有另一种(IMO 更好)的方法:您应该模拟您正在使用的库。python 的一个示例模拟助手是mox

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

于 2010-10-28T23:49:35.077 回答