首页 > 解决方案 > pytest 代码和路由的实际烧瓶会话之间的行为差​​异

问题描述

我有以下简单的 pytest 案例,它测试删除操作:

def test_delete_club(client, systemAdmin, operationalCountry1, club1):
    rv = loginTo(client, '/admin/clubs/1', '+00000000000','testpassword')
    decodedRv = rv.data.decode('utf-8')
    assert '<td>testClub1</td>' in decodedRv
    rv = client.get('/admin/delete_club/1', follow_redirects = True)
    decodedRv = rv.data.decode('utf-8')
    assert '<td>testClub1</td>' not in decodedRv
    #ensure club1 does not exist in the database either
    c = Club.query.get(1)
    assert c is None
    # make sure club roles are deleted along with the club
    clubRoles = Role.query.filter(Role.club_id == club1.id).all()
    assert len(clubRoles)

基本上,它会点击删除 URL ( /admin/delete_club/1),并且在重定向之后,它断言数据库中既没有这样的俱乐部,也没有与该俱乐部关联的任何角色。

我正在使用 TDD(测试驱动开发)。所以我在相关路由代码之前写了上面的测试用例。我的路由方法如下所示:

@flaskApp.route('/admin/delete_club/<int:id>', methods=['GET'])
@login_required
def delete_club(id):
    '''Deletes the club identified by the id'''
    if not isCurrentUserSysAdmin():
        #TODO better error handling
        return 'you can not touch this'

    clubToDelete = Club.query.get_or_404(id)
    logging.debug('About to delete club: {}'.format(clubToDelete))
    opCountryId = clubToDelete.operationalcountry_id
    try:
        db.session.delete(clubToDelete)
        logging.debug('Deleted club: {}'.format(clubToDelete))
    except:
        flash('Error deleting club')
        logging.error('Error deleting club. Club Details: {}'.format(clubToDelete))
    return redirect(url_for('clubs', countryid = opCountryId))

嗯,到目前为止一切顺利。测试用例顺利通过。当时我很开心。我想在真正的网页上试一试。然后我注意到,虽然删除操作成功了,但在重定向的页面上,我试图删除的俱乐部仍然存在。

然后我发现了BUGdb.session.commit() :删除俱乐部实例实体后我只是忘记添加了。该更改修复了网页。

但是,我仍然很困惑为什么我的测试用例没有抱怨它,为什么它根本没有失败?同样,测试用例在没有 commit 语句的情况下也可以工作

来自经验丰富的 Flask/Python 开发人员的任何想法?

标签: pythonflaskpytestflask-sqlalchemy

解决方案


简而言之,db.session.delete将事务注册到内存中执行。但没有db.commit它就不会在数据库上执行查询。此方法将仅更改数据库的本地表示。我建议您使用上下文管理器with session.begin()


推荐阅读