首页 文章

意外AssertionError:单个测试未使用上一步中的登录用户

提问于
浏览
1

我遵循http://www.patricksoftwareblog.com/flask-tutorial/的教程,我相信它基于https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world . 适合初学者的好东西 .

当我通过前端手动测试我的代码(工作正常)时,我得到了不同的结果 . 通过pytest .

我的测试试图显示需要登录的“组” endpoints (标准@login_required装饰器) .

  • 我最初测试用户在尝试获取没有登录的 endpoints 时获取登录页面("Knock knock") . 这可以手动和通过pytest工作 .

  • 我登录用户 . 如果我从登录中检查响应,我可以清楚地看到"Welcome back Pete!"成功消息 .

  • 我的第二个断言收到来自URL /login?next=%2Fgroups 的响应,指示 /groups endpoints 在其之前没有登录/身份验证的情况下被调用,并且断言失败 . 手动测试可按预期工作 . 为什么单个测试在下一步中没有使用相同的用户/会话组合?

Test with the problem is the first snippet below:

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)

1 回答

  • 1

    我将总结我所做的评论,给出了如何解决这个问题的答案 .

    使用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()
    

    创建测试客户端允许您使用各种测试功能,并使用适当的应用程序上下文访问烧瓶请求 .

相关问题