postgresql 当py.test无提示挂起时该怎么办?

6ljaweal  于 2023-02-08  发布在  PostgreSQL
关注(0)|答案(7)|浏览(101)

在使用py.test时,我有一些测试在SQLite中运行良好,但是当我切换到Postgresql时会静默地挂起。我该如何调试类似的东西?有没有一种“详细”模式可以运行测试或设置断点?更一般地说,当pytest静默地挂起时,标准的攻击计划是什么?我尝试过使用pytest-timeout,并使用$ py.test --timeout=300运行测试,但是测试仍然挂起,屏幕上没有任何活动

vybvopom

vybvopom1#

我在使用Flask和SQLAlchemy时遇到了同样的SQLite/Postgres问题,类似于Gordon Fierce,但是我的解决方案不同,Postgres对表锁和连接要求严格,所以在拆卸时显式关闭会话连接为我解决了这个问题。
我的工作代码:

@pytest.yield_fixture(scope='function')
def db(app):
    # app is an instance of a flask app, _db a SQLAlchemy DB
    _db.app = app
    with app.app_context():
        _db.create_all()

    yield _db

    # Explicitly close DB connection
    _db.session.close()

    _db.drop_all()

参考:SQLAlchemy

rqcrx0a6

rqcrx0a62#

为了回答“我该如何调试这样的东西?”
1.使用py.test -m trace --trace运行以获取python调用的跟踪信息。
1.一个选项(对任何阻塞的unix二进制文件有用)是使用strace -p <PID>附加到进程。查看它可能阻塞的系统调用或系统调用循环。例如,阻塞调用gettimeofday
1.要获得更详细的py.test输出,请安装pytest-sugar. pip install pytest-sugar并使用pytest.py --verbose . . .https://pypi.python.org/pypi/pytest-sugar运行测试

cngwdvgl

cngwdvgl3#

我在测试一个使用SQLAlchemy的Flask应用程序时遇到了类似的问题,看起来pytest很难用它的request.addfinalizer方法和postgresql一起运行拆卸。
以前我有:

@pytest.fixture
def db(app, request):
    def teardown():
        _db.drop_all()

    _db.app = app
    _db.create_all()

    request.addfinalizer(teardown)

    return _db

(_db是我从www.example.com导入的SQLAlchemy的一个示例extensions.py)但是如果每次调用数据库fixture时删除数据库:

@pytest.fixture
def db(app, request):
    _db.app = app
    _db.drop_all()
    _db.create_all()
    return _db

那么pytest在你第一次测试后就不会挂了。

rxztt3cl

rxztt3cl4#

在不知道代码中的中断是什么的情况下,最好的方法是隔离出失败的测试,并在其中设置一个断点来查看。我使用pudb而不是pdb,因为如果您没有使用IDE,那么它确实是调试python的最佳方法。
例如,可以在测试文件中添加以下内容:

import pudb
...

def test_create_product(session):
    pudb.set_trace()
    # Create the Product instance
    # Create a  Price instance
    # Add the Product instance to the session. 
    ...

那就用

py.test -s --capture=no test_my_stuff.py

现在,您将能够看到脚本锁定的确切位置,并在执行的特定时刻检查堆栈和数据库,否则就像大海捞针一样。

jvlzgdj9

jvlzgdj95#

我遇到这个问题已经有一段时间了(尽管我没有使用SQLite),测试套件在本地运行良好,但是在CircleCI(Docker)中失败了。
我的问题最终在于:
1.对象的基础实现使用了线程
1.对象的__del__通常会结束线程
1.我的测试套件没有调用__del__,因为它应该调用
我想我应该补充一下我是如何得出这个结论的。其他的答案是这样的:

  • 发现使用pytest-timeout没有帮助,测试在完成后挂起
  • 通过pytest --timeout 5调用
  • 版本:pytest==6.2.2, pytest-timeout==1.4.2
  • 运行pytest -m trace --tracepytest --verbose也没有产生有用的信息

最后我不得不把所有的东西都评论出来,包括:
1.所有conftest.py代码和测试代码
1.缓慢取消/重新评论区域并确定根本原因
1.最终解决方案:使用工厂fixture添加终结器以调用__del__

fkvaft9z

fkvaft9z6#

在我的例子中,Flask应用程序没有检查if __name__ == '__main__':,所以它执行了app.start(),而这不是我的意图。
您可以在这里阅读更多详细信息。

btqmn9zl

btqmn9zl7#

在我的例子中,当Assert失败时,比较4 MB数据时,diff运行得非常慢。

with open(path, 'rb') as f:
    assert f.read() == data

修复人:

with open(path, 'rb') as f:
    eq = f.read() == data
    assert eq

相关问题