当py.test静默挂起时该怎么办?

时间:2014-10-14 00:24:30

标签: sqlite postgresql timeout hang pytest

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

6 个答案:

答案 0 :(得分:14)

我遇到了与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参考:http://docs.sqlalchemy.org/en/rel_0_8/faq.html#my-program-is-hanging-when-i-say-table-drop-metadata-drop-all

答案 1 :(得分:5)

在测试使用SQLAlchemy的Flask应用程序时,我遇到了与pytest和Postgresql类似的问题。似乎pytest很难使用postgresql的request.addfinalizer方法进行拆解。

以前我曾经:

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

    _db.app = app
    _db.create_all()

    request.addfinalizer(teardown)

    return _db

(_db是我从extensions.py导入的SQLAlchemy的一个实例) 但是,如果每次调用数据库夹具时都删除数据库:

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

然后pytest在第一次测试后不会挂起。

答案 2 :(得分:4)

回答问题"我将如何进行类似的调试?"

  1. 使用py.test -m trace --trace运行以获取python调用的痕迹。

  2. 一个选项(对任何卡住的unix二进制文件很有用)是使用pip install pytest-sugar附加到进程。查看可能存在的系统调用或系统调用循环。例如卡住了gettimeofday

  3. 更详细的py.test输出安装pytest-sugar。 pytest.py --verbose . . .并使用{{1}}运行测试 https://pypi.python.org/pypi/pytest-sugar

答案 3 :(得分:1)

不知道代码中的内容是什么,最好的方法是隔离失败的测试并在其中设置断点以查看。注意:我使用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

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

答案 4 :(得分:0)

在我的情况下,Flask应用程序没有检查if __name__ == '__main__':所以当我不打算执行app.start()时。

您可以阅读更多详情here

答案 5 :(得分:0)

我遇到这个问题已经有一段时间了(虽然我没有使用 SQLite)。测试套件在本地运行良好,但在 CircleCI (Docker) 中失败。

我的问题最终是:

  1. 对象的底层实现使用了线程
  2. 对象的 __del__ 通常会结束线程
  3. 我的测试套件没有按应有的方式调用 __del__

我想我会补充一下我是怎么想出来的。其他答案建议如下:

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

我最终不得不对所有内容进行评论,包括:

  1. 所有 conftest.py 代码和测试代码
  2. 慢慢取消注释/重新注释区域并确定根本原因
  3. 最终解决方案:使用工厂设备添加终结器以调用 __del__