Как подавить ImportWarning в скрипте unittest на Python

В настоящее время я запускаю скрипт unittest, который успешно проходит различные указанные тесты с назойливым сообщением ImportWarning в консоли:

...../lib/python3.6/importlib/_bootstrap.py:219: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
  return f(*args, **kwds)
....
----------------------------------------------------------------------
Ran 7 tests in 1.950s

OK

Скрипт запускается с этой основной функцией:

if __name__ == '__main__':
    unittest.main()

Я читал, что предупреждения могут быть подавлены, если сценарий вызывается следующим образом:

python  -W ignore:ImportWarning -m unittest testscript.py

Однако есть ли способ указать это предупреждение игнорирования в самом скрипте, чтобы мне не приходилось вызывать -W ignore:ImportWarning каждый раз при запуске тестового скрипта?

Заранее спасибо.


person Mysterio    schedule 26.06.2018    source источник
comment
Предупреждение, похоже, исходит от одного из тестов, основанных на пакете pandas, который полагается на кучу зависимостей.   -  person Mysterio    schedule 26.06.2018


Ответы (3)


Чтобы программно предотвратить появление таких предупреждений, настройте свой код так, чтобы:

import warnings
if __name__ == '__main__':
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', category=ImportWarning)
        unittest.main()

Источник: https://stackoverflow.com/a/40994600/328469

Обновление:

@billjoie, безусловно, прав. Если OP решит сделать ответ 52463661 принятым ответом, я согласен с этим. Я могу подтвердить, что следующее эффективно для подавления таких предупреждающих сообщений во время выполнения с использованием Python версий 2.7.11, 3.4.3, 3.5.4, 3.6.5 и 3.7.1:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import unittest
import warnings


class TestPandasImport(unittest.TestCase):
    def setUp(self):
        warnings.simplefilter('ignore', category=ImportWarning)

    def test_01(self):
        import pandas  # noqa: E402
        self.assertTrue(True)

    def test_02(self):
        import pandas  # noqa: E402
        self.assertFalse(False)


if __name__ == '__main__':
    unittest.main()

Однако я думаю, что OP должен рассмотреть возможность более глубокого исследования целей кода приложения модульных тестов и попытаться определить конкретный импорт пакета или операцию, которая вызывает фактическое предупреждение, а затем подавить предупреждение как можно ближе к место в коде, где происходит нарушение. Это позволит избежать подавления предупреждений во всем классе модульного теста, что может непреднамеренно скрывать предупреждения от других частей программы.

Вне модульного теста, где-то в коде приложения:

with warnings.catch_warnings():
    warnings.simplefilter('ignore', category=ImportWarning)
    # import pandas
    # or_ideally_the_application_code_unit_that_imports_pandas()

Может потребоваться небольшая работа, чтобы изолировать конкретное место в коде, которое вызывает предупреждение, или использовать стороннее программное обеспечение, которое вызывает предупреждение, но разработчик получит более четкое представление о причине предупреждения, и это будет только улучшить общую ремонтопригодность программы.

person Nels    schedule 30.07.2018

У меня была та же проблема, и запуск моего скрипта unittest с оператором warnings.simplefilter(), как описано Нелсом, не сработал для меня. Согласно этому источнику, это потому что:

[...] начиная с Python 3.2, модуль unittest был обновлен для использования фильтра по умолчанию модуля предупреждений при запуске тестов, и [...] сбрасывается до фильтра по умолчанию перед каждым тестом, что означает, что любое изменение, которое, как вы думаете, вы вносите в масштабе сценария, используя warnings.simplefilter («игнорировать») в начале вашего сценария, переопределяется между каждым тестом.

Этот же источник рекомендует обновлять фильтр внутри каждой тестовой функции напрямую или с помощью элегантного декоратора. Более простое решение - определить фильтр предупреждений внутри метода setUp() unittest, который запускается непосредственно перед каждым тестом.

import unittest
class TestSomething(unittest.TestCase):
    def setUp(self):
        warnings.simplefilter('ignore', category=ImportWarning)
        # Other initialization stuff here

    def test_a(self):
        # Test assertion here.

if __name__ == '__main__':
    unittest.main()
person billjoie    schedule 23.09.2018

У меня было такое же предупреждение в Pycharm для одного теста при использовании unittest. Это предупреждение исчезло, когда я перестал пытаться импортировать библиотеку во время теста (я переместил импорт наверх, где он должен быть). Я знаю, что запрос был на подавление, но это также заставит его исчезнуть, если это произойдет только в выбранном количестве тестов.

person L Miller    schedule 16.04.2021