2

用pytest-httpserver来测试requests

 3 years ago
source link: https://note.qidong.name/2019/01/pytest-httpserver/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用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()

以上的几个测试函数,展示了一些常用的手段:

其它

这个库当然还支持HTTP协议的其它内容,包括headersmimetypcontent_type等。 这些在测试中不常用,就不介绍了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK