rui*_*eco 7 python unit-testing pytest flask
我正在尝试使用 pytest 为 Flask 应用程序编写单元测试。我有一个应用工厂:
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
Run Code Online (Sandbox Code Playgroud)
和一个测试类:
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
Run Code Online (Sandbox Code Playgroud)
但是当我运行我的测试时,我收到以下错误:
RuntimeError: Attempted to generate a URL without the application context being pushed. This has to be executed when application context is available.
Run Code Online (Sandbox Code Playgroud)
谷歌搜索告诉我(我认为)使用测试客户端应该创建一个自动应用程序上下文。我错过了什么?
使用测试客户端发出请求确实会推送应用程序上下文(间接)。但是,您将url_for测试请求调用内部的可视化事实与实际上在内部调用的想法混淆了。该url_for呼叫首先进行评价的结果传递给client.get。
url_for通常用于在应用程序内生成 URL ,单元测试是外部的。通常,您只需在请求中准确写入您要测试的 URL,而不是生成它。
self.client.get('/users/create')
Run Code Online (Sandbox Code Playgroud)
如果您真的想在url_for这里使用,则必须在应用程序上下文中进行。请注意,当您处于应用程序上下文而不是请求上下文中时,您必须设置SERVER_NAMEconfig 并通过_external=False. 但同样,您可能应该只写出您尝试测试的 URL。
app.config['SERVER_NAME'] = 'localhost'
with self.app.app_context():
url = url_for(..., _external=False)
self.client.get(url, ...)
Run Code Online (Sandbox Code Playgroud)
您可以url_for()在使用方法创建的测试请求上下文中调用app.test_request_context()。有三种方法可以实现这一目标。
由于您已经创建了设置和拆卸方法,就像我通常对单元测试所做的那样,您可以在设置方法中推送测试请求上下文,然后将其弹出到拆卸方法中:
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
Run Code Online (Sandbox Code Playgroud)
此外,您也可以只使用pytest-flask。使用 pytest-flask,您可以访问上下文绑定对象(url_for、request、session),而无需上下文管理器:
def test_app(client):
assert client.get(url_for('myview')).status_code == 200
Run Code Online (Sandbox Code Playgroud)
如果你不想安装该插件,你可以使用以下固定装置来做类似的事情(从 pytest-flask 的源代码中窃取):
@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 teardown
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4176 次 |
| 最近记录: |