httpretty的配置管理器
项目描述
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 导出 FixtureManager、get、put、post、delete、head、patch、options、connect、first_request、last_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 列表 - 要运行的固定值函数的名称
* 字符串 - 要运行的固定值函数的名称
返回
返回一个正在运行的 fixture_manager 实例。这可以用来 访问固定值及其请求信息。
.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 对象 - 关于传入请求的信息
结构由 httpretty 管理
更多详情可以从源代码中读取
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 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e027d361eb73e202d42909b23a04e0725a222145783371b33f4abdce55208173 |
|
MD5 | 8d7969a2e4b3d4f581cd67337dc5d362 |
|
BLAKE2b-256 | f6b582b95bad0ccddbe006ad9fddabccb5feedd5cf889d56fd6b865aaf8afd40 |