我试着用pytest为一个烧瓶应用程序编写单元测试。我有一个应用程序工厂:
def create_app():
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
import os
app.secret_key = os.urandom(24)
from models import db
db.init_app(app)
return app还有一堂测试课:
class TestViews(object):
@classmethod
def setup_class(cls):
cls.app = create_app()
cls.app.testing = True
cls.client = cls.app.test_client()
@classmethod
def teardown_class(cls):
cls.app_context.pop()
def test_create_user(self):
"""
Tests the creation of a new user.
"""
view = TestViews.client.get(url_for('create_users')).status_code == 200但是,当我运行测试时,我会得到以下错误:
RuntimeError: Attempted to generate a URL without the application context being pushed. This has to be executed when application context is available.谷歌这告诉我(我认为)使用测试客户端应该创建一个自动的应用程序上下文。我遗漏了什么?
发布于 2017-10-09 12:51:57
使用测试客户端发出请求确实会(间接地)推送应用程序上下文。但是,您混淆了这样一个事实,即url_for在测试请求调用中是视觉上的,而它实际上是在内部调用的。首先计算url_for调用,然后将结果传递给client.get。
url_for通常用于在应用程序中生成URL,单元测试是外部的。通常,您只需在请求中准确地编写要测试的URL,而不是生成它。
self.client.get('/users/create')如果您真的想在这里使用url_for,您必须在应用程序上下文中这样做。注意,当您在应用程序上下文中而不是请求上下文中时,您必须设置SERVER_NAME配置并传递_external=False。但是,您可能应该写出您想要测试的URL。
app.config['SERVER_NAME'] = 'localhost'
with self.app.app_context():
url = url_for(..., _external=False)
self.client.get(url, ...)发布于 2021-02-22 10:40:33
您可以在用url_for()方法创建的测试请求上下文中调用app.test_request_context()。实现这一目标的方法有三种。
用设置和拆卸
由于您已经创建了安装和拆卸方法,就像我通常对unittest所做的一样,您可以在安装方法中推送一个测试请求上下文,然后在teardown方法中弹出它:
class TestViews(object):
@classmethod
def setup_class(cls):
cls.app = create_app()
cls.app.testing = True
cls.client = cls.app.test_client()
cls.context = cls.app.test_request_context() # create the context object
cls.context.push() # push the context
@classmethod
def teardown_class(cls):
cls.context.pop() # pop the context
def test_create_user(self):
"""
Tests the creation of a new user.
"""
view = TestViews.client.get(url_for('create_users')).status_code == 200用热瓶
此外,您也可以使用热瓶。使用pytest-flask,您可以访问上下文绑定对象(url_for、request、session),而无需上下文管理器:
def test_app(client):
assert client.get(url_for('myview')).status_code == 200自置夹具
如果您不想安装这个插件,您可以使用下面的固定装置来做类似的事情(从pytest-烧瓶的源头偷来的):
@pytest.fixture
def app():
app = create_app('testing')
return app
@pytest.fixture(autouse=True)
def _push_request_context(request, app):
ctx = app.test_request_context() # create context
ctx.push() # push
def teardown():
ctx.pop() # pop
request.addfinalizer(teardown) # set teardownhttps://stackoverflow.com/questions/46646603
复制相似问题