用pytest-httpserver来测试requests
2019-01-28 22:10:05 +08 字数:905 标签: Python Test在Python程序中,用requests发起网络请求,是常见的操作。 但如何测试,是一个麻烦的问题。 如果是单元测试,可以用pytest-mock;但如果是集成测试,用Stub的思路,则可以考虑pytest-httpserver。
本文介绍如何使用pytest-httpserver,来对requests等涉及网络请求操作的代码,进行集成测试。
基本原理 ¶
利用pytest的fixture机制,为测试函数提供一个httpserver
。
这是一个基于werkzeug启动(make_server
)的真实服务,启动在当前环境中,host:port
自动生成,默认不可见。
from werkzeug.serving import make_server
对这个Server的特定Request,设置特定的Response,以达到测试的目的。
简单示例 ¶
以下提供一个简单的代码样例,便于理解完整流程。
import requests
from pytest_httpserver import HTTPServer
from pytest_httpserver.httpserver import RequestHandler
def test_root(httpserver: HTTPServer):
handler = httpserver.expect_request('/')
assert isinstance(handler, RequestHandler)
handler.respond_with_data('', status=200)
response = requests.get(httpserver.url_for('/'))
assert response.status_code == 200
httpserver
需要设置两方面内容,输入(Request)和输出(Response)。
先通过expect_request
指定输入,再通过respond_with_data
指定输出。
最后,通过url_for
来获取随机生成Server的完整URL。
这里,仅对/
的Request响应,返回status=200
的Response。
如果在使用一些不方便使用fixtures的场景,可以通过with
来使用相同功能。
def test_root():
with HTTPServer() as httpserver:
handler = httpserver.expect_request('/')
assert isinstance(handler, RequestHandler)
handler.respond_with_data('', status=200)
response = requests.get(httpserver.url_for('/'))
assert response.status_code == 200
更多代码示例 ¶
代码示例,有时比API文档更管用。 (更何况这个库还没有文档。)
def test_status(httpserver: HTTPServer):
uri = '/status'
handler = httpserver.expect_request(uri)
handler.respond_with_data('', status=302)
response = requests.get(httpserver.url_for(uri))
assert response.status_code == 302
def test_method(httpserver: HTTPServer):
uri = '/method'
handler = httpserver.expect_request(uri=uri, method='GET')
handler.respond_with_data('', status=200)
response = requests.get(httpserver.url_for(uri))
assert response.status_code == 200
response = requests.post(httpserver.url_for(uri))
assert response.status_code == 500
def test_respond_with_data(httpserver: HTTPServer):
uri = '/data'
handler = httpserver.expect_request(
uri=uri,
method='POST',
)
handler.respond_with_data('good')
response = requests.post(httpserver.url_for(uri))
assert response.status_code == 200
assert response.content == b'good'
def test_respond_with_json(httpserver: HTTPServer):
uri = '/data'
expect = {'a': 1, 'b': 2}
handler = httpserver.expect_request(
uri=uri,
method='POST',
)
handler.respond_with_json(expect)
handler.respond_with_data
response = requests.post(httpserver.url_for(uri))
assert response.status_code == 200
assert expect == response.json()
以上的几个测试函数,展示了一些常用的手段:
- 不同
uri
- 指定HTTP response status codes
- 指定HTTP request methods
- 指定返回的内容(Content)
- 指定返回内容为JSON
- 未指定Response的,统一返回状态码500
其它 ¶
这个库当然还支持HTTP协议的其它内容,包括headers
、mimetyp
、content_type
等。
这些在测试中不常用,就不介绍了。