Unexpected AssertionError: single test not using logged in user from previous step
Unexpected AssertionError: single test not using logged in user from previous step
我正在学习 http://www.patricksoftwareblog.com/flask-tutorial/, which I believe is based on https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world 的教程。适合初学者的好东西。
我通过前端手动测试我的代码时得到了不同的结果(工作正常)v.s。通过 pytest.
我的测试试图显示需要登录的 "groups" 端点(标准 @login_required 装饰器)。
- 我最初测试用户在没有登录的情况下尝试获取端点时获取登录页面 ("Knock knock")。这可以通过 pytest 手动进行。
- 我登录了一个用户。如果我检查登录的响应,我可以清楚地看到 "Welcome back Pete!" 成功消息。
- 我的第二个断言收到来自 URL
/login?next=%2Fgroups
的响应,指示调用 /groups
端点时前面没有 login/authentication 并且断言失败。手动测试按预期工作。为什么单个测试在下一步中不使用相同的 user/session 组合?
测试问题是下面的第一个片段:
def test_groups(app):
assert b'Knock knock' in get(app, "/groups").data
login(app, "pete@testmail.com", "pete123")
assert b'Test group 1' in get(app, "/groups").data
我的"get"函数供参考:
def get(app, endpoint: str):
return app.test_client().get(endpoint, follow_redirects=True)
我的"login"函数供参考:
def login(app, email="testuser@testmail.com", password="testing"):
return app.test_client().post('/login', data=dict(email=email, password=password), follow_redirects=True)
应用程序(来自@pytest.mark.usefixtures('app')在测试模块中导入的conftest夹具)供参考:
@pytest.fixture
def app():
"""An application for the tests."""
_app = create_app(DevConfig)
ctx = _app.test_request_context()
ctx.push()
yield _app
ctx.pop()
登录路径供参考:
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm(request.form)
if request.method == 'POST':
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is not None and user.is_correct_password(form.password.data):
user.authenticated = True
user.last_login = user.current_login
user.current_login = datetime.now()
user.insert_user()
login_user(user)
flash(f'Welcome back {user.name}!', 'success')
return redirect(url_for('our_awesome_group.index'))
else:
flash('Incorrect credentials! Did you already register?', 'error')
else:
flash_errors(form)
return render_template('login.html', form=form)
组团路线供参考:
@app.route('/groups')
@login_required
def groups():
groups_and_users = dict()
my_group_uuids = Membership.list_groups_per_user(current_user)
my_groups = [Group.query.filter_by(uuid=group).first() for group in my_group_uuids]
for group in my_groups:
user_uuids_in_group = Membership.list_users_per_group(group)
users_in_group = [User.query.filter_by(uuid=user).first() for user in user_uuids_in_group]
groups_and_users[group] = users_in_group
return render_template('groups.html', groups_and_users=groups_and_users)
我要总结一下我发表的评论,这些评论给出了如何解决这个问题的答案。
使用 Pytest 和 Flask 创建测试应用程序时,有几种不同的方法。
使用适当的应用上下文 create a test client 的建议方法是使用如下内容:
@pytest.fixture
def client():
""" Creates the app from testconfig, activates test client and context then makes the db and allows the test client
to be used """
app = create_app(TestConfig)
client = app.test_client()
ctx = app.app_context()
ctx.push()
db.create_all()
yield client
db.session.close()
db.drop_all()
ctx.pop()
这会在推送应用程序上下文的同时创建客户端,因此您可以注册诸如数据库之类的东西并为测试客户端创建表。
第二种方式显示在OP的问题中使用app.test_request context
@pytest.fixture
def app():
"""An application for the tests."""
_app = create_app(DevConfig)
ctx = _app.test_request_context()
ctx.push()
yield _app
ctx.pop()
然后在另一个 pytest fixture 中创建测试客户端
@pytest.fixture
def client(app):
return app.test_client()
创建测试客户端允许您使用各种测试功能,并允许使用适当的应用程序上下文访问 Flask 请求。
我正在学习 http://www.patricksoftwareblog.com/flask-tutorial/, which I believe is based on https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world 的教程。适合初学者的好东西。
我通过前端手动测试我的代码时得到了不同的结果(工作正常)v.s。通过 pytest.
我的测试试图显示需要登录的 "groups" 端点(标准 @login_required 装饰器)。
- 我最初测试用户在没有登录的情况下尝试获取端点时获取登录页面 ("Knock knock")。这可以通过 pytest 手动进行。
- 我登录了一个用户。如果我检查登录的响应,我可以清楚地看到 "Welcome back Pete!" 成功消息。
- 我的第二个断言收到来自 URL
/login?next=%2Fgroups
的响应,指示调用/groups
端点时前面没有 login/authentication 并且断言失败。手动测试按预期工作。为什么单个测试在下一步中不使用相同的 user/session 组合?
测试问题是下面的第一个片段:
def test_groups(app):
assert b'Knock knock' in get(app, "/groups").data
login(app, "pete@testmail.com", "pete123")
assert b'Test group 1' in get(app, "/groups").data
我的"get"函数供参考:
def get(app, endpoint: str):
return app.test_client().get(endpoint, follow_redirects=True)
我的"login"函数供参考:
def login(app, email="testuser@testmail.com", password="testing"):
return app.test_client().post('/login', data=dict(email=email, password=password), follow_redirects=True)
应用程序(来自@pytest.mark.usefixtures('app')在测试模块中导入的conftest夹具)供参考:
@pytest.fixture
def app():
"""An application for the tests."""
_app = create_app(DevConfig)
ctx = _app.test_request_context()
ctx.push()
yield _app
ctx.pop()
登录路径供参考:
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm(request.form)
if request.method == 'POST':
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is not None and user.is_correct_password(form.password.data):
user.authenticated = True
user.last_login = user.current_login
user.current_login = datetime.now()
user.insert_user()
login_user(user)
flash(f'Welcome back {user.name}!', 'success')
return redirect(url_for('our_awesome_group.index'))
else:
flash('Incorrect credentials! Did you already register?', 'error')
else:
flash_errors(form)
return render_template('login.html', form=form)
组团路线供参考:
@app.route('/groups')
@login_required
def groups():
groups_and_users = dict()
my_group_uuids = Membership.list_groups_per_user(current_user)
my_groups = [Group.query.filter_by(uuid=group).first() for group in my_group_uuids]
for group in my_groups:
user_uuids_in_group = Membership.list_users_per_group(group)
users_in_group = [User.query.filter_by(uuid=user).first() for user in user_uuids_in_group]
groups_and_users[group] = users_in_group
return render_template('groups.html', groups_and_users=groups_and_users)
我要总结一下我发表的评论,这些评论给出了如何解决这个问题的答案。
使用 Pytest 和 Flask 创建测试应用程序时,有几种不同的方法。
使用适当的应用上下文 create a test client 的建议方法是使用如下内容:
@pytest.fixture
def client():
""" Creates the app from testconfig, activates test client and context then makes the db and allows the test client
to be used """
app = create_app(TestConfig)
client = app.test_client()
ctx = app.app_context()
ctx.push()
db.create_all()
yield client
db.session.close()
db.drop_all()
ctx.pop()
这会在推送应用程序上下文的同时创建客户端,因此您可以注册诸如数据库之类的东西并为测试客户端创建表。
第二种方式显示在OP的问题中使用app.test_request context
@pytest.fixture
def app():
"""An application for the tests."""
_app = create_app(DevConfig)
ctx = _app.test_request_context()
ctx.push()
yield _app
ctx.pop()
然后在另一个 pytest fixture 中创建测试客户端
@pytest.fixture
def client(app):
return app.test_client()
创建测试客户端允许您使用各种测试功能,并允许使用适当的应用程序上下文访问 Flask 请求。