How to suppress ImportWarning in a python unittest script
Asked Answered
A

4

14

I am currently running a unittest script which successfully passes the various specified test with a nagging ImportWarning message in the console:

...../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

The script is run with this main function:

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

I have read that warnings can be surpressed when the script is called like this:

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

However, is there a way of specifying this ignore warning in the script itself so that I don't have to call -W ignore:ImportWarning every time that the testscript is run?

Thanks in advance.

Amytal answered 26/6, 2018 at 14:26 Comment(1)
The warning seems to come from one of the tests relying on pandas package which relies on a bunch of dependenciesAmytal
C
15

To programmatically prevent such warnings from showing up, adjust your code so that:

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

Source: https://mcmap.net/q/828041/-unable-to-suppress-deprecation-warnings

Update:

@billjoie is certainly correct. If the OP chooses to make answer 52463661 the accepted answer, I am OK with that. I can confirm that the following is effective at suppressing such warning messages at run-time using python versions 2.7.11, 3.4.3, 3.5.4, 3.6.5, and 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()

However, I think that the OP should consider doing some deeper investigation into the application code targets of the unit tests, and try to identify the specific package import or operation which is causing the actual warning, and then suppress the warning as closely as possible to the location in code where the violation takes place. This will obviate the suppression of warnings throughout the entirety of one's unit test class, which may be inadvertently obscuring warnings from other parts of the program.

Outside the unit test, somewhere in the application code:

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

It could take a bit of work to isolate the specific spot in the code that is either causing the warning or leveraging third-party software which causes the warning, but the developer will obtain a clearer understanding of the reason for the warning, and this will only improve the overall maintainability of the program.

Chanson answered 30/7, 2018 at 19:7 Comment(0)
U
13

I had the same problem, and starting my unittest script with a warnings.simplefilter() statement, as described by Nels, dit not work for me. According to this source, this is because:

[...] as of Python 3.2, the unittest module was updated to use the warnings module default filter when running tests, and [...] resets to the default filter before each test, meaning that any change you may think you are making scriptwide by using warnings.simplefilter(“ignore”) at the beginning of your script gets overridden in between every test.

This same source recommends to renew the filter inside of each test function, either directly or with an elegant decorator. A simpler solution is to define the warnings filter inside unittest's setUp() method, which is run right before each test.

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()
Upstate answered 23/9, 2018 at 6:38 Comment(0)
S
3

Solutions with def setUp suppress warnings for all methods within class. If you don't want to suppress it for all of them, you can use decorator.

From Neural Dump:

import warnings
def ignore_warnings(test_func):
    def do_test(self, *args, **kwargs):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            test_func(self, *args, **kwargs)
    return do_test

Then you can use it to decorate single test method in your test class:

class TestClass(unittest.TestCase):
    @ignore_warnings
    def test_do_something_without_warning()
        self.assertEqual(whatever)

    def test_something_else_with_warning()
        self.assertEqual(whatever)
Spiro answered 16/3, 2022 at 13:46 Comment(0)
D
1

I had the same warning in Pycharm for one test when using unittest. This warning disappeared when I stopped trying to import a library during the test (I moved the import to the top where it's supposed to be). I know the request was for suppression, but this would also make it disappear if it's only happening in a select number of tests.

Damek answered 16/4, 2021 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.