При использовании py.test у меня есть некоторые тесты, которые отлично работают с SQLite, но беспомощно висят, когда я переключаюсь на Postgresql. Как я могу отладить что-то подобное? Есть ли "подробный" режим, в котором я могу выполнить свои тесты или установить точку останова? В более общем плане, каков стандартный план атаки, когда pytest кивает молча? Я пробовал использовать pytest-timeout и запускал тест с $py.test --timeout = 300, но тесты по-прежнему зависают без активности на экране бы то ни было
Что делать, когда py.test висит тихо?
Ответ 1
Я столкнулся с той же проблемой SQLite/Postgres, что и Flask и SQLAlchemy, похожей на 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
Ответ 2
У меня была аналогичная проблема с pytest и Postgresql при тестировании приложения Flask, которое использовало SQLAlchemy. Кажется, что 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 - экземпляр SQLAlchemy, который я импортирую из extensions.py) Но если я удаляю базу данных каждый раз, когда вызывается база данных:
@pytest.fixture
def db(app, request):
_db.app = app
_db.drop_all()
_db.create_all()
return _db
Тогда pytest не будет висеть после вашего первого теста.
Ответ 3
Чтобы ответить на вопрос "Как я могу отладить что-то подобное?"
-
Запустите с py.test -m trace -trace, чтобы получить трассировку вызовов python.
-
Один вариант (полезный для любого застрявшего двоичного файла unix) заключается в подключении к процессу с помощью
strace -p <PID>
. Посмотрите, какой системный вызов он может застрять или цикл системных вызовов. например застрявший вызов gettimeofday -
Для более подробного вывода py.test установите pytest-sugar.
pip install pytest-sugar
И запустить тест с помощьюpytest.py --verbose . . .
https://pypi.python.org/pypi/pytest-sugar
Ответ 4
Не зная, что происходит в коде, лучший способ - изолировать тест, который терпит неудачу, и установить в нем точку останова. Примечание. Я использую pudb вместо pdb, потому что это действительно лучший способ отладки python, если вы не используете IDE.
Например, вы можете в тестовом файле:
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
Теперь вы сможете точно определить, где блокируется script, и изучить стек и базу данных в этот конкретный момент выполнения. В противном случае это похоже на поиск иглы в стоге сена.
Ответ 5
В моем случае приложение Flask не проверило if __name__ == '__main__':
, поэтому оно выполнило app.start()
, когда это не было моим намерением.
Здесь вы можете прочитать более подробную информацию .