【问题标题】:Pytest teardown of postgresql database in Flask is happening before tests are done在测试完成之前,Flask 中的 postgresql 数据库的 Pytest 拆解正在发生
【发布时间】:2021-01-09 16:27:07
【问题描述】:

当我使用 SQLite 作为测试数据库时,以下测试运行良好。但是,该应用程序现在需要 Postgresql,这会“导致”测试挂起。在运行时,当我通过select * from pg_stat_activity 进行检查时,teardown 或 db.drop_all() 进程正在尝试删除表(有些已被删除),而 test_login_logout 中的第二个查询仍在运行。

如果我删除db.drop_all(),测试运行良好,但显然数据库没有被清除。我究竟做错了什么?谢谢!

@pytest.fixture(scope='module')
def test_client():
    app = create_app('testing')
    with app.test_client() as testing_client:
            with app.app_context():
                yield testing_client


@pytest.fixture(scope='module')
def init_database(test_client):

    db.create_all()

    admin_role = Role(name='admin')
    db.session.add(admin_role)

    user = User(username='testuser', password='password', role=admin_role)
    db.session.add(user)

    db.session.commit()

    yield

    db.drop_all()


class TestPublic:

    def test_login_logout(self, test_client, init_database):
        response = test_client.post('/login', data=dict(
            username='testuser', password='password'), follow_redirects=True)
        assert response.status_code == 200
        assert b"Login successful." in response.data

        response = test_client.post('/login', data=dict(
            username='x', password='x'), follow_redirects=True)
        assert response.status_code == 200
        assert b"Invalid username or password." in response.data

        response = test_client.get('/logout', follow_redirects=True)
        assert response.status_code == 200
        assert b"You have been logged out." in response.data

【问题讨论】:

    标签: python postgresql flask pytest


    【解决方案1】:

    从那里删除db.drop_all()语句并添加这个函数,它会在所有测试完成后自动调用:

    def pytest_sessionfinish(session, exitstatus):
        """ whole test run finishes. """
        db.drop_all()
    

    来源:https://docs.pytest.org/en/stable/reference.html#pytest.hookspec.pytest_sessionfinish

    【讨论】:

      【解决方案2】:

      我注意到 postgresql 中的查询状态说它是“idle_in_transaction”,并且经过几次搜索后this article 表明在产量之后添加db.session.remove() 将有助于解决锁定问题。现在可以了!供参考:

      @pytest.fixture(scope='module')
      def init_database(test_client):
      
          db.drop_all()
          db.create_all()
      
          admin_role = Role(name='admin')
          db.session.add(admin_role)
      
          user = User(username='testuser', password='password', role=admin_role)
          db.session.add(user)
      
          db.session.commit()
      
          yield
      
          db.session.remove()
          db.drop_all()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-26
        • 2019-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-13
        • 1970-01-01
        相关资源
        最近更新 更多