【问题标题】:testing urllib2 application, http responses loaded from files测试 urllib2 应用程序,从文件加载的 http 响应
【发布时间】:2010-07-19 04:15:27
【问题描述】:

我的 python 应用程序使用 urllib2 向许多 url 发出许多 http 请求。我想构建一个单元测试套件来测试我的数据解析和错误处理代码。

我有一个充满测试数据的目录,其中包含许多文件,每个文件都包含一个 http 响应、标头和响应数据。 (使用 curl -i)在某些情况下,这些文件包含 http 错误消息(需要测试错误处理)

理想情况下,我想创建一个模拟对象来替换 urllib2.urlopen 并返回一个模拟响应对象。

我想知道是否有一种简单的方法可以让 urllib2 直接从文件加载 HTTP 响应并让 urllib2 解析此数据以创建适当的响应对象(就像从 url 读取响应一样。

我尝试使用使用“file://”协议构建的 url,但是文件顶部的 http 响应标头未被正确读取或解析。

另外,我正在考虑编写一个小型 Web 服务器类来提供测试文件,但这似乎比我想要的要多一些工作。让 urllib2 以某种方式从我已经保存在文件中的 http 响应重建响应对象会更容易(无需构建 Web 服务器来再次为它们提供服务)

有什么想法吗?

【问题讨论】:

    标签: python urllib2


    【解决方案1】:

    我认为最好的方法是模拟 httplib.HTTPConnection 的一个子集(在下面调用生成的类 mockcon 以获得具体性)并添加一个使用它的处理程序和子类化 HTTPHandler(在 build_opener 中使用 - - 子类化意味着它可以替换 build_opener 默认使用的HTTPHandler):

    class MockHTTPHandler(urllib2.HTTPHandler):
    
        def http_open(self, req):
            return self.do_open(mockcon, req)
    

    mockcon 类必须提供方法 do_open 调用 -- 有几个可以是假的(即接受和忽略任意 args 和 kwds 并且什么都不做):

    set_debuglevel
    _set_tunnel
    request
    

    (可能对request 的第二个参数感兴趣,因为它提供了 URL 的“选择器”部分)。

    mockcon__init__ 方法将 URL 的主机部分作为第一个 arg(即,当然是 self 之后的第一个),并且应该忽略后面的 kwds(用于设置超时)。

    mockconget_response 方法(没有参数,当然超出了self)必须返回一个 http 响应对象——即,一个类似文件的可读对象,它也具有属性 .msg.status , 和 .reason,以及一个方法 get_full_url() 来返回 URL。

    您可以为后一个角色使用实际的 httplib.HTTPResponse 实例,但您必须使用一个具有 makefile 参数的模拟/虚拟 arg 对其进行初始化(忽略其 args 和 kwds 并返回任何内容),并且紧随其后初始化它,将其 .fp 参数重置为 rb 打开文件,准确给出真正的 HTTP 响应将在其套接字上接收到的字节。

    我认为为整个urllib2.urlopen 调用构建一个成熟的模拟可能比尝试重用urllib2(以及它在内部使用的httplib)的大部分功能更简单,尽管可能并不完全就像您认为更多工作​​的“本地 Web 服务器”方法一样简单。但是值得考虑所有三种方法(模拟肯定是最轻量级/最快的操作,本地Web服务器最慢......并且还需要通过在它们前面加上http://localhost:someport/来以某种方式修改URL,当然) .

    【讨论】:

      【解决方案2】:

      服务器方法绝对不是更多的工作,它可能是所有替代方案中最简单和最少的工作。

      查看:http://docs.python.org/library/simplehttpserver.html

      一个 7 行的 python 程序,当从某个目录运行时,它将通过 HTTP 提供所有文件(以及递归地,子目录中的任何文件)。

      您可以让您的单元测试代码启动和停止服务器,这样即使没有进行测试,您也不需要让它继续运行。

      【讨论】:

      • 虽然简单的测试很容易,但对于单元测试来说,启动服务器运行(也是一个新进程)通常不是一个好方法,模拟外部实体和功能是最好的方法。对于许多其他类型的测试,这是一个不错的选择。一个不太强烈的理由来拒绝投票!
      • 我同意,一个适当的模拟解决方案总体上会更好。我只是在回应这样一种说法,即这样做工作量太大。就快速启动和运行而言,这可能是最简单的事情。从长远来看,这绝对不是最好的,我根本没有争论
      猜你喜欢
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 2012-01-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多