跳过主内容

pytest插件,用于本地测试服务器连接。

项目描述

PyPI Version Supported Python versions https://img.shields.io/badge/code%20style-black-000000.svg pre-commit.ci status

pytest-localserver

pytest-localserver 是一个针对 pytest 测试框架的插件,它允许您在本地测试服务器连接。

有时简单地使用 monkeypatching urllib2.urlopen() 并不能解决问题,例如,如果您使用 urllib2.Request,定义自己的打开器/处理程序,或者使用 httplib。在这些情况下,拥有一个本地运行的、表现得就像真实服务器一样的 HTTP 服务器可能会很有用 [1]。那么,无需再找!

快速入门

假设您有一个用于抓取 HTML 的函数,该函数只需指向一个 URL 即可。

import requests
def scrape(url):
    html = requests.get(url).text
    # some parsing happens here
    # ...
    return result

您希望完整地测试此函数,而无需依赖于无法控制其内容的远程服务器,您也不想浪费时间设置复杂的机制来模拟或修补处理实际 HTTP 请求的底层 Python 模块(实际上有多个)。那么您该怎么办呢?

您只需使用 pytest 的 funcargs 功能,并在本地模拟整个服务器!

def test_retrieve_some_content(httpserver):
    httpserver.serve_content(open('cached-content.html').read())
    assert scrape(httpserver.url) == 'Found it!'

这里发生的事情是在测试期间,在本地主机的随机端口上启动一个 HTTP 服务器,该服务器将提供您告诉它的内容,表现得就像真实的服务器。

额外的优势是,您可以测试在网络问题发生时,您的代码是否表现良好。

def test_content_retrieval_fails_graciously(httpserver):
    httpserver.serve_content('File not found!', 404)
    pytest.raises(ContentNotFoundException, scrape, httpserver.url)

同样,这也适用于 SMTP 服务器。

def test_sending_some_message(smtpserver):
    mailer = MyMailer(host=smtpserver.addr[0], port=smtpserver.addr[1])
    mailer.send(to='bob@example.com', from_='alice@example.com',
        subject='MyMailer v1.0', body='Check out my mailer!')
    assert len(smtpserver.outbox)==1

这里启动了一个 SMTP 服务器,该服务器接受发送给它的电子邮件。这里的一个好功能是,您实际上可以检查消息是否被接收以及发送了什么,通过查看 smtpserver 的 outbox

真的非常简单!

可用的 funcargs

以下是可用的 funcargs 的简要概述。有关更多详细信息,我建议您查看代码本身。

httpserver

提供在 localhost 上运行的线程化 HTTP 服务器实例。它有以下属性

  • code - HTTP 响应代码(int)

  • content - 下一个响应的内容(str,bytes 或两者的可迭代对象)

  • headers - 响应头(dict)

  • chunked - 是否以分块编码响应(枚举)

  • store_request_data - 是否存储请求数据供以后使用

一旦设置了这些属性,后续的所有请求都将使用这些值进行响应,直到它们被更改或服务器停止。更改这些的更方便方法是

httpserver.serve_content(content=None, code=200, headers=None, chunked=pytest_localserver.http.Chunked.NO, store_request_data=True)

chunked 属性或参数可以设置为

  • Chunked.YES,告诉服务器始终应用分块编码

  • Chunked.NO,告诉服务器从不应用分块编码

  • Chunked.AUTO,告诉服务器仅在 Transfer-Encoding 头包括 chunked 时应用分块编码

如果应用了分块编码,content 中的每个 str 或 bytes 将成为响应中的一个分块。

您可以使用 store_request_data=False 来禁用将请求数据加载到内存中。这将使得使用 httpserver.requests[index].data 检查请求数据变得不可能,但在需要发送大量数据且不需要检查该数据时,这样做可能是有意义的。

服务器地址可以在属性中找到

  • url

它是元组 server_address(主机作为字符串,端口号作为整数)的字符串表示。

如果您想检查哪些表单字段已被 POST,请尝试

httpserver.serve_content(..., show_post_vars=True)

它将以可解析文本的形式显示它们。

如果您需要检查发送到服务器的请求,可以在属性中找到所有接收到的请求的列表

  • requests

它是一个包含 werkzeug.wrappers.Request 对象的列表。

httpsserver

httpserver 相同,只是具有 SSL 加密。

smtpserver

提供线程化的 SMTP 服务器,API 与 smtpd.SMTPServer 类似(Python 标准库中已弃用的类),在本地主机上运行。它有以下属性

  • addr - 服务器地址作为元组(主机作为字符串,端口号作为整数)

  • outbox - 接收到的 email.message.Message 实例的列表。

将您的 WSGI 应用程序作为测试服务器使用

从版本 0.3 开始,您现在可以使用 WSGI 应用程序 在测试服务器上运行

from pytest_localserver.http import WSGIServer

def simple_app(environ, start_response):
    """Simplest possible WSGI application"""
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

@pytest.fixture
def testserver(request):
    """Defines the testserver funcarg"""
    server = WSGIServer(application=simple_app)
    server.start()
    request.addfinalizer(server.stop)
    return server

def test_retrieve_some_content(testserver):
    assert scrape(testserver.url) == 'Hello world!\n'

有关 WSGI 的更多信息,请参阅以下页面: http://wsgi.readthedocs.org/en/latest/learn.html

下载和安装

您可以通过运行以下命令来安装插件

pip install pytest-localserver

或者,从 PyPI 获取最新稳定版本,或从 Github 获取最新的 bleeding-edge

许可证和致谢

此插件在 MIT 许可证下发布。您可以在 LICENSE 文件中找到许可证的全文。

版权 (C) 2010-2022 Sebastian Rahlf 及其他人(见 AUTHORS)。

本软件包的部分基于其他人的想法或代码

  • 我借鉴了从 linkchecker 中的一些 httpserver 的实现想法。

  • SMTP 服务器的实现基于 Adam Feuer、Matt Branthwaite 和 Troy Frever 的 Mailsink recipe

  • HTTPS 实现基于 Sebastien Martini 的工作。

谢谢大家!

开发和未来计划

请随意克隆存储库并添加您自己的更改。始终欢迎拉取请求!

git clone https://github.com/pytest-dev/pytest-localserver

如果您发现任何错误,请提交 报告

可以使用 tox 运行测试。

我已有一些建议用于未来的版本

  • 支持 FTP、SSH(可能基于 twisted?)

  • 使 SMTP outbox 的使用与 django.core.mail.outbox 一样方便

  • 在这里添加您的想法!

准备发布

对于软件包维护者,以下是发布新版本的方法

  1. 确保 CHANGES 文件与最新的更改保持最新。

  2. 确保您要发布的版本上的所有测试都通过。

  3. 使用 Github 上的新发布表单(或某些等效方法)创建新版本,遵循先前发布的模式。

    • 每个版本都必须基于一个标签。您可以选择先创建标签(例如,使用 git tag),然后从这个标签发布版本,或者让 GitHub 在发布过程中自动创建标签;两种方法都可以。

    • 标签名称 必须 是符合 PEP 440 的版本号,并以前缀 v 开头,确保至少包含三个版本号组件(例如 v0.6.0)。

    • “自动生成发布说明”按钮将有助于总结自上次发布以来的更改。

  4. 通过发布工作流程页面或您收到的关于“部署审查”的电子邮件中的链接,转到为新发布创建的工作流程运行,点击“审查部署”,然后批准或拒绝两个部署,一个用于测试 PyPI,一个用于真实 PyPI。 (除非发生真正奇怪的事情,否则通常不需要拒绝部署。)一旦部署被批准,GitHub 将自动上传文件。


项目详情


下载文件

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

源分布

pytest_localserver-0.9.0.tar.gz (30.2 kB 查看哈希值)

上传时间

构建分布

pytest_localserver-0.9.0-py3-none-any.whl (20.7 kB 查看哈希值)

上传时间 Python 3

支持者