我在Flask Cookiecutter上构建了我的测试,我的所有其他测试都工作得很好。只有在测试使用g元素的函数时才会出现问题,比如views.py文件中的g.user。
我的conftest.py与Flask-cookiecutter的完全相同,再加上Flask-Testing中的the faking resources and context trick。
### conftest.py ###
...
from contextlib import contextmanager
from flask import appcontext_pushed, g
@contextmanager
def user_set(app, user):
def handler(sender, **kwargs):
g.user = user
with appcontext_pushed.connected_to(handler, app):
yield
...下面是我的测试文件:
### test_file.py ###
from .conftest import user_set
import pytest
from my_app.utils import presave_posted_settings # <-- fn I want to test
@pytest.fixture()
def form_data():
return {...bunch of data..}
@pytest.mark.usefixtures("form_data")
class TestPresaveSettings:
"""Test cases for checking attributes before saving"""
def test_presave_posted_settings(self, form_data, user, testapp):
"""User meals are selected in form"""
with user_set(testapp, user): #<-- testapp and user available from flask-cookiecutter conftest.py
assert presave_posted_settings(form_data)当我在test_file.py上运行测试时,我看到:
user = <User 'user0'>, testapp = <webtest.app.TestApp object at 0x1101ee160>
def test_presave_posted_settings(self, form_data, user, testapp):
"""User meals are selected in form"""
with user_set(testapp, user):
> assert presave_posted_settings(form_data)
test_utils.py:20:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../my_app/utils.py:26: in presave_posted_settings
g.user.breakfast = g.user.lunch = g.user.dinner = g.user.snack = g.user.dessert = False
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <flask.g of 'my_app'>, name = 'user'
def __getattr__(self, name):
if name == '__members__':
return dir(self._get_current_object())
> return getattr(self._get_current_object(), name)
E AttributeError: '_AppCtxGlobals' object has no attribute 'user'我已经用谷歌搜索过了,大多数示例都使用Unittest,或者将所有的pytest都放在一个文件中。我想坚持拥有多个测试文件的模式,每个测试文件都利用conftest.py,但是我终生无法弄清楚如何设置它,以便可以测试使用g元素的函数。谢谢!
发布于 2021-08-27 17:36:37
这个问题很老了,但它与我遇到的问题最相关,我有一个简单的解决方案。
给出一个测试客户端的夹具,就像这样(宽恕温和的伪代码):
@pytest.fixture()
def test_client():
app = create_app()
with app.test_client() as test_client:
with app.app_context():
yield test_client我试着创建一个修改g的fixture,def modify_g(test_client)认为依赖于test_client提供的上下文将使它可用。由于一些我可能不完全理解的关于pytest如何评估fixture的事情,事实并非如此。您会得到相同的'_AppCtxGlobals' object has no attribute错误。但是,如果您创建一个中间函数,那么它的计算结果是正确的,并且修改后的g对象将出现在测试上下文中。
@pytest.fixture()
def pre_test_client():
app = create_app()
with app.test_client() as test_client:
with app.app_context():
yield test_client
@pytest.fixture()
def test_client(pre_test_client):
yield pre_test_client
@pytest.fixture()
def modify_g(pre_test_client):
g.user = 'test'如果定义了g,那么使用g的测试将会起作用:
def test_g_data(test_client, modify_g):这意味着它非常容易模拟数据中的许多不同状态,并将它们作为fixture放入测试函数中。
诚然,我并不确切地理解为什么这是必要的,所以我希望能就pytest如何评估这些fixture做出任何解释。
请注意,这忽略了Flask提供的appcontext_pushed解决方案,但这是使其工作的一种非常快速和简单的方法,尽管可能不是最佳解决方案。
https://stackoverflow.com/questions/42964347
复制相似问题