如何使用 pytest 测试 Flask 视图上下文和模板?

Phi*_*ord 5 pytest flask

我正在使用 pytest 和 Flask 来测试我的视图和模板,但我不清楚如何最好地做到这一点。

我知道我可以测试 HTML 输出的内容,例如:

def test_my_view(test_client):
    # test_client is a fixture representing app.test_client()
    response = test_client.get("/my-url")
    assert b"<h1>My page title</h1>" in response.data
Run Code Online (Sandbox Code Playgroud)

但有些事情我不确定如何最好地做:

  1. 如何测试视图正在使用哪个模板?

  2. 如何测试视图发送到模板的上下文?(例如检查它login_form是 的实例LoginForm

  3. 如果我想测试是否存在更复杂的 HTML 标记(例如<form>具有正确action属性的标记),这是检查整个标记(例如<form method="get" class="form-lg" action="/other-url">)是否存在的唯一方法,即使我不关心其他属性?action假设页面上也有其他表单,我如何才能检查?

Phi*_*ord 7

我意识到 1 和 2 可以通过像这个问题中的解决方案来解决,稍微改变一下以与 pytest 一起使用。

假设我们有这个 Flask 视图:

from flask import render_template
from app import app

@app.route("/my/view")
def my_view():
    return render_template("my/template.html", greeting="Hello!")
Run Code Online (Sandbox Code Playgroud)

我们想要测试调用该 URL 是否使用了正确的模板,并且传递了正确的上下文数据。

首先,创建一个可重复使用的夹具:

from flask import template_rendered
import pytest

@pytest.fixture
def captured_templates(app):
    recorded = []

    def record(sender, template, context, **extra):
        recorded.append((template, context))

    template_rendered.connect(record, app)
    try:
        yield recorded
    finally:
        template_rendered.disconnect(record, app)
Run Code Online (Sandbox Code Playgroud)

我还有一个用于test_client在测试中发出请求的固定装置(类似于testappFlask Cookiecutter 中的固定装置test_client本教程中的固定装置)。

然后编写你的测试:

def test_my_view(test_client, captured_templates):
    response = test_client.get("/my/view")

    assert len(captured_templates) == 1

    template, context = captured_templates[0]

    assert template.name = "my/template.html"

    assert "greeting" in context
    assert context["greeting"] == "Hello!"
Run Code Online (Sandbox Code Playgroud)

请注意, 中可能有多个元素captured_templates,具体取决于您的视图的作用。