跳转到主要内容

httpretty的配置管理器

项目描述

Build Status

httpretty的配置管理器

功能

  • 在测试中重用响应

  • 允许在请求之间维护状态

  • 访问过去的请求信息

    • 基于每个配置文件

    • 跨所有配置文件

本工具是为了解决在测试期间与Elasticsearch通信的问题而编写的。对于我们的使用情况,mock扩展性不好,将httpretty配置文件放在我们的基本测试用例中不切实际。为了解决这个问题,我们编写了一个配置文件管理器,httpretty-fixtures

入门指南

使用以下命令安装模块:pip install httpretty_fixtures

# Load in our dependencies
import json
import unittest

import httpretty_fixtures
import requests


# Set up our fixture manager
class FakeElasticsearch(httpretty_fixtures.FixtureManager):
    @httpretty_fixtures.get('http://localhost:9200/my_index/my_document/my_id')
    def es_index(self, request, uri, res_headers):
        return (200, res_headers, json.dumps({
            '_index': 'my_index',
            '_type': 'my_document',
            '_id': 'my_id',
            '_version': 1,
            'found': True,
        }))


# Define our tests
class MyTestCase(unittest.TestCase):
    @FakeElasticsearch.run(['es_index'])
    def test_retrieve_from_es(self, fake_elasticsearch):
        """Verify we can retrieve an item from Elasticsearch"""
        # Make our request and verify we hit Elasticsearch
        res = requests.get('http://localhost:9200/my_index/my_document/my_id?first')
        self.assertEqual(res.status_code, 200)
        self.assertEqual(res.json()['_index'], 'my_index')

        # Make a second request for demonstration purposes
        requests.get('http://localhost:9200/my_index/my_document/my_id?second')

        # Introspect our request received on `FakeElasticsearch`
        fixture = fake_elasticsearch.es_index
        self.assertEqual(fixture.first_request.path, '/my_index/my_document/my_id?first')
        self.assertEqual(fixture.last_request.path, '/my_index/my_document/my_id?second')
        self.assertEqual(len(fixture.requests), 2)
        self.assertEqual(fixture.requests[0].path, '/my_index/my_document/my_id?first')
        self.assertEqual(fixture.requests[1].path, '/my_index/my_document/my_id?second')

        # Access request information from all `httpretty` requests
        self.assertEqual(httpretty_fixtures.first_request().path, '/my_index/my_document/my_id?first')
        self.assertEqual(httpretty_fixtures.last_request().path, '/my_index/my_document/my_id?second')
        self.assertEqual(len(httpretty_fixtures.requests()), 2)
        self.assertEqual(httpretty_fixtures.requests()[0].path, '/my_index/my_document/my_id?first')
        self.assertEqual(httpretty_fixtures.requests()[1].path, '/my_index/my_document/my_id?second')

文档

httpretty-fixtures 导出 FixtureManagergetputpostdeleteheadpatchoptionsconnectfirst_requestlast_request 以及 requests 作为方法和变量。

我们将把这个包称为 httpretty_fixtures

FixtureManager()

用于设置一系列固定值(fixtures)的类。这个类应该被继承到另一个具有自己一系列固定值的类中。

class FakeElasticsearch(httpretty_fixtures.FixtureManager):
    @httpretty_fixtures.get('http://localhost:9200/my_index/my_document/my_id')
    def es_index(self, request, uri, res_headers):
        return (200, res_headers, json.dumps({'content': 'goes here'}))

fixture_manager.run(fixtures)

装饰器,用于在函数运行时执行一系列固定值

  • fixtures 列表 - 要运行的固定值函数的名称

    • * 字符串 - 要运行的固定值函数的名称

我们将把服务器实例作为参数传递给装饰函数。从服务器中,我们可以 访问每个实例的固定值信息和请求

class FakeElasticsearch(httpretty_fixtures.FixtureManager):
    @httpretty_fixtures.get('http://localhost:9200/my_index/my_document/my_id')
    def es_index(self, request, uri, res_headers):
        return (200, res_headers, json.dumps({}))

class MyTestCase(unittest.TestCase):
    # The `es_index` fixture will be live for all of this test case
    @FakeElasticsearch.run(['es_index'])
    def test_retrieve_from_es(self, fake_elasticsearch):
        """Verify we can retrieve an item from Elasticsearch"""
        # Make our request and verify we hit Elasticsearch
        res = requests.get('http://localhost:9200/my_index/my_document/my_id')

fixture_manager.start(fixtures)

以一组固定值启动 HTTPretty

  • fixtures 列表 - 要运行的固定值函数的名称

    • * 字符串 - 要运行的固定值函数的名称

返回

.start() 将无限期地运行 HTTPretty,直到调用 .stop()

fixture_manager.stop()

停止一个正在运行的 HTTPretty 实例。这应该在某个时间点之后始终运行 .start()

httpretty_fixtures.{verb}(*register_uri_args, **register_uri_kwargs)

装饰器,用于在某个 HTTP 动词下注册固定值函数

这是所有可能的 HTTP 动词的摘要

@httpretty_fixtures.get()
@httpretty_fixtures.put()
@httpretty_fixtures.post()
@httpretty_fixtures.delete()
@httpretty_fixtures.head()
@httpretty_fixtures.patch()
@httpretty_fixtures.options()
@httpretty_fixtures.connect()

这些动词中的每一个都将其参数/关键字参数传递给 HTTPretty 的 register_uri` 函数

如果您想将某些参数应用到您的固定值上,相对于 HTTPretty,可以通过这种方式实现。

https://github.com/gabrielfalcao/HTTPretty/tree/0.8.3#usage

@httpretty_fixtures.get("http://underdog.io/")

函数签名

httpretty_fixtures 利用 httpretty 的动态回调功能

https://github.com/gabrielfalcao/HTTPretty/tree/0.8.3#dynamic-responses-through-callbacks

因此,我们期望我们的装饰器接收一个与以下签名匹配的函数

@httpretty_fixtures.get("http://underdog.io/")
def request_handler(self, request, uri, res_headers):
    res_tuple = (status_code, res_headers, body)
    return res_tuple

# Example
@httpretty_fixtures.get("http://underdog.io/")
def hello(self, request, uri, res_headers):
    return (200, res_headers, 'Hello World!')

签名如下

  • request_handler 函数 - 请求回调的处理程序

  • self 对象 - 在 FixtureManager 之上扩展的类的实例

  • uri 对象 - 关于传入请求的信息

  • res_headers 对象 - 为请求提供的默认响应头

    • 这些应该在 res_tuple 中修改和/或传递

  • res_tuple 元组 - 我们响应的信息集合

    • [0] 整数 - 为响应提供的状态码

      • 例如,200 将是 200 HTTP 状态码

    • [1] 对象 - 修改后或提供的作为参数提供的头集

    • [2] 字符串 - 请求的响应体

      • 在上面的例子中,我们回复了 'Hello World!',但这也可能是 JSON、XML 或您需要的任何东西

函数属性

httpretty_fixtures 提供辅助属性来访问过去的请求信息。为了参考,我们将把固定值称为 fixed

  • fixture.first_request - 访问 fixture 在当前实例 .run() 中收到的第一个请求

    • 如果没有收到请求,则此值将为 None

  • fixture.last_request - 访问 fixture 在当前实例 .run() 中收到的最后一个请求

    • 如果没有收到请求,则此值将为 None

  • fixture.requests - 收到的所有请求列表

通过返回的服务器,可以通过 .run() 装饰器或 .start() 访问 fixture

class MyTestCase(unittest.TestCase):
    # The `es_index` fixture will be live for all of this test case
    @FakeElasticsearch.run(['es_index'])
    def test_retrieve_from_es(self, fake_elasticsearch):
        # Access our `fixture` and its properties
        fake_elasticsearch.es_index
        fake_elasticsearch.es_index.first_request
        fake_elasticsearch.es_index.last_request
        fake_elasticsearch.es_index.requests

httpretty_fixtures.first_request()

访问 HTTPretty 收到的第一个请求的别名。

警告:如果您在其他位置使用 HTTPretty,则这些请求也将被注册。

httpretty_fixtures.last_request()

访问 HTTPretty 收到的最后一个请求的别名。

警告:如果您在其他位置使用 HTTPretty,则这些请求也将被注册。

httpretty_fixtures.requests()

访问 HTTPretty 收到的所有请求的别名。

警告:如果您在其他位置使用 HTTPretty,则这些请求也将被注册。

示例

在请求之间保留状态

在这个示例中,我们将对多个请求进行计数,以表明状态正在被保留。

# Load in our dependencies
import unittest

import httpretty_fixtures
import requests


# Set up our fixture manager
class CounterServer(httpretty_fixtures.FixtureManager):
    def __init__(self):
        self.count = 0
        super(CounterServer, self).__init__()

    @httpretty_fixtures.get('http://localhost:9000/')
    def counter(self, request, uri, res_headers):
        self.count += 1
        return (200, res_headers, str(self.count))


# Define our tests
class MyTestCase(unittest.TestCase):
    @CounterServer.run(['counter'])
    def test_counter_state(self, counter_server):
        """Verify we can preserve state between requests"""
        # Make our first request and verify its count
        res = requests.get('http://localhost:9000/')
        self.assertEqual(res.status_code, 200)
        self.assertEqual(res.text, '1')

        # Make our second request and verify its count
        res = requests.get('http://localhost:9000/')
        self.assertEqual(res.status_code, 200)
        self.assertEqual(res.text, '2')

    @CounterServer.run(['counter'])
    def test_counter_alternate_state(self, counter_server):
        """Verify state is not maintained between separate `FixtureManager.run()'s`"""
        res = requests.get('http://localhost:9000/')
        self.assertEqual(res.status_code, 200)
        self.assertEqual(res.text, '1')

贡献

由于没有正式的风格指南,请注意维护现有的编码风格。为任何新功能或更改的功能添加单元测试。通过 nosetests 进行测试。

许可证

版权(c)2015 Underdog.io

根据 MIT 许可证授权。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码发行版

httpretty_fixtures-2.1.1.tar.gz (10.3 kB 查看哈希值)

上传时间 源代码

由以下支持