How to view runtime warnings in PyCharm when running tests using pytest? - python

When running tests in PyCharm 2022.3.2 (Professional Edition) using pytest (6.2.4) and Python 3.9 I get the following result in the PyCharm console window:
D:\cenv\python.exe "D:/Program Files (x86)/JetBrains/PyCharm 2022.3.2/plugins/python/helpers/pycharm/_jb_pytest_runner.py" --path D:\tests\test_k.py
Testing started at 6:49 PM ...
Launching pytest with arguments D:\tests\test_k.py --no-header --no-summary -q in D:\tests
============================= test session starts =============================
collecting ... collected 5 items
test_k.py::test_init
test_k.py::test_1
test_k.py::test_2
test_k.py::test_3
test_k.py::test_4
======================= 5 passed, 278 warnings in 4.50s =======================
Process finished with exit code 0
PASSED [ 20%]PASSED [ 40%]PASSED [ 60%]PASSED [ 80%]PASSED [100%]
So the actual warnings don't show. Only the number of warnings (278) is shown.
I tried:
selecting: Pytest: do not add "--no-header --no-summary -q" in advanced settings
Setting Additional arguments to -Wall in the Run/Debug configurations window
Setting Interpreter options to -Wall in the Run/Debug configurations window
and all permutations, all to no avail. Is there a way to show all runtime warnings when running tests using pytest in PyCharm in the PyCharm Console window?
EDIT:
#Override12
When I select do not add "--no-header --no-summary -q" in advanced settings I get the following output:
D:\Projects\S\SHARK\development_SCE\cenv\python.exe "D:/Program Files (x86)/JetBrains/PyCharm 2020.3.4/plugins/python/helpers/pycharm/_jb_pytest_runner.py" --path D:\Projects\S\SHARK\development_SCE\cenv\Lib\site-packages\vistrails-3.5.0rc0-py3.9.egg\vistrails\packages\SHARK\analysis\tests\test_fairing_1_plus_k.py -- --jb-show-summary
Testing started at 10:07 AM ...
Launching pytest with arguments D:\Projects\S\SHARK\development_SCE\cenv\Lib\site-packages\vistrails-3.5.0rc0-py3.9.egg\vistrails\packages\SHARK\analysis\tests\test_fairing_1_plus_k.py in D:\Projects\S\SHARK\development_SCE\cenv\Lib\site-packages\vistrails-3.5.0rc0-py3.9.egg\vistrails\packages
============================= test session starts =============================
platform win32 -- Python 3.9.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- D:\Projects\S\SHARK\development_SCE\cenv\python.exe
cachedir: .pytest_cache
rootdir: D:\Projects\S\SHARK\development_SCE\cenv\Lib\site-packages\vistrails-3.5.0rc0-py3.9.egg\vistrails\packages
plugins: pytest_check-1.0.5
collecting ... collected 5 items
SHARK/analysis/tests/test_fairing_1_plus_k.py::test_init
SHARK/analysis/tests/test_fairing_1_plus_k.py::test_without_1_k_fairing
SHARK/analysis/tests/test_fairing_1_plus_k.py::test_1_k_fairing_given
SHARK/analysis/tests/test_fairing_1_plus_k.py::test_without_1_k_fairing_only_3_values_under_threshold
SHARK/analysis/tests/test_fairing_1_plus_k.py::test_1_k_fairing_given_only_3_values_under_threshold
============================== warnings summary ===============================
......\pyreadline\py3k_compat.py:8
D:\Projects\S\SHARK\development_SCE\cenv\lib\site-packages\pyreadline\py3k_compat.py:8: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.10 it will stop working
return isinstance(x, collections.Callable)
......\nose\importer.py:12
D:\Projects\S\SHARK\development_SCE\cenv\lib\site-packages\nose\importer.py:12: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
from imp import find_module, load_module, acquire_lock, release_lock
SHARK/analysis/tests/test_fairing_1_plus_k.py: 276 warnings
D:\Projects\S\SHARK\development_SCE\cenv\lib\site-packages\pymarin\objects\key.py:1101: UserWarning: siUnits is deprecated, use siUnit
warnings.warn('siUnits is deprecated, use siUnit')
-- Docs: https://docs.pytest.org/en/stable/warnings.html
======================= 5 passed, 278 warnings in 5.79s =======================
Process finished with exit code 0
PASSED [ 20%]PASSED [ 40%]PASSED [ 60%]PASSED [ 80%]PASSED [100%]
So 4 warnings are displayed. However I would like to see all 278 warnings.
When I run pytest from the command line outside PyCharm I get the same result. So it seems to be a pytest problem and it seems that it has nothing to do with PyCharm.

I think you could also try adding verbosity or collect warnings in a programatic way, by changing how you execute the tests.

The solution is a combination of two things:
Setting 'do not add "--no-header --no-summary -q"' in advanced settings as #Override12 suggested.
When the same warning is issued multiple times, only the first time is displayed. In my case solving the first warning reduced the number of warnings from 278 to 2.

Related

pytest --cov is telling me I haven't imported something that I have

Here's what I run, and what I get:
me $ pytest --cov MakeInfo.py
================================================================================ test session starts =================================================================================
platform darwin -- Python 3.7.4, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
rootdir: /Users/me/Documents/workspace-vsc/Pipeline/src/python
plugins: cov-2.12.1, arraydiff-0.3, remotedata-0.3.2, doctestplus-0.4.0, openfiles-0.4.0
collected 42 items
test_MakeInfo.py ............ [ 28%]
test_MakeJSON.py ... [ 35%]
test_convert_refflat_to_bed.py .. [ 40%]
test_generate_igv_samples.py ... [ 47%]
test_sample_info_to_jsons.py .... [ 57%]
read_coverage/test_intervaltree.py ......... [ 78%]
util/test_util.py ......... [100%]**Coverage.py warning: Module MakeInfo.py was never imported**. (module-not-imported)
Coverage.py warning: No data was collected. (no-data-collected)
WARNING: Failed to generate report: No data to report.
/Users/me/opt/anaconda3/lib/python3.7/site-packages/pytest_cov/plugin.py:271: PytestWarning: Failed to generate report: No data to report.
self.cov_controller.finish()
Here's the top of test_MakeInfo.py:
import pytest
import os
import sys
import json
import MakeInfo
from MakeInfo import main, _getNormalTumorInfo
What I'm looking for: Tell me how much of MakeInfo.py is covered by tests in test_MakeInfo.py
What I'm getting: confused
Is my command wrong for what I want? Nothing calls into MakeInfo.py, it's stand alone and called from the command line. So of course none of the other tests are including it.
Is there a way to tell pytest --cov to look at this test file, and the source file, and ignore everything else?
Try changing the call to just the python module name MakeInfo instead of the file name MakeInfo.py. Or if it is in an inner subdirectory, use the dot . notation e.g. some_dir.some_subdir.MakeInfo
pytest --cov MakeInfo
So, it turns out that in this case the order of arguments is key
pytest test_MakeInfo.py --cov
Runs pytest on my one test file, and gives me coverage information for the one source file
pytest --cov test_MakeInfo.py
Tries to run against every test file (one of which was written by someone else on my team, and apparently uses a different test tool, so it throws up errors when pytest tries to run it)
pytest --cov MakeInfo
Is part way there: it runs all the tests, including the ones that fail, but then gives me the coverage information I want
So #Niel's answer is what you want if you have multiple test files targeting a single source file

Pytest spending most time post-test?

I run a single function through pytest that (in the example below) takes 71 seconds to run. However, pytest spends an additional 6-7 minutes doing... something. I can tell from a log file that the intended test is executed at the beginning of the 7 minutes, but I cannot imagine what's going on afterwards (and apparently it's not the teardown, if the "slowest durations" output is to be believed).
The pytest function itself is extremely minimal:
def test_preprocess_and_train_model():
import my_module.pipeline as pipeline # noqa
pipeline.do_pipeline(do_s3_upload=False,
debug=True, update_params={'tf_verbosity': 0})
If I run test_preprocess_and_train_model() by hand (e.g., if I invoke the function through an interpreter rather than through pytest), it takes about 70 seconds.
What is happening and how can I speed it up?
▶ pytest --version
pytest 6.2.2
▶ python --version
Python 3.8.5
▶ time pytest -k test_preprocess_and_train_model -vv --durations=0
====================================================== test session starts =======================================================
platform darwin -- Python 3.8.5, pytest-6.2.2, py-1.9.0, pluggy-0.13.1 -- /usr/local/opt/python#3.8/bin/python3.8
cachedir: .pytest_cache
rootdir: /Users/blah_blah_blah/tests
collected 3 items / 2 deselected / 1 selected
test_pipelines.py::test_preprocess_and_train_model PASSED [100%]
======================================================== warnings summary ========================================================
test_pipelines.py::test_preprocess_and_train_model
/Users/your_name_here/Library/Python/3.8/lib/python/site-packages/tensorflow/python/autograph/impl/api.py:22: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
test_pipelines.py: 3604341 warnings
sys:1: DeprecationWarning: PY_SSIZE_T_CLEAN will be required for '#' formats
test_pipelines.py::test_preprocess_and_train_model
/Users/your_name_here/Library/Python/3.8/lib/python/site-packages/tensorflow/python/keras/engine/training.py:2325: UserWarning: `Model.state_updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
warnings.warn('`Model.state_updates` will be removed in a future version. '
-- Docs: https://docs.pytest.org/en/stable/warnings.html
======================================================= slowest durations ========================================================
71.88s call test_pipelines.py::test_preprocess_and_train_model
0.00s teardown test_pipelines.py::test_preprocess_and_train_model
0.00s setup test_pipelines.py::test_preprocess_and_train_model
================================= 1 passed, 2 deselected, 3604343 warnings in 422.15s (0:07:02) ==================================
pytest -k test_preprocess_and_train_model -vv --durations=0 305.95s user 158.42s system 104% cpu 7:26.14 total
I thought I'd post the resolution of this in case it helps anyone else.
theY4Kman's suggestion of just profiling the code was excellent. My own code ran in 70 seconds as expected and exited cleanly, but it produced 3.6M warning messages. Each warning message in pytest triggered an os.stat() check (to figure out which line of code had produced the warning), and evaluating 3.6M system calls took 5 minutes or so. If I commented out the heart of warning_record_to_str() in pytest's warnings.py, then pytest took about 140 seconds (i.e., most of the problem was solved).
This also explained why the performance depended on the platform (Mac vs Ubuntu), because the number of error messages differed vastly.
There seem to be two sad conclusions, if I'm understanding things correctly:
Even if I use the --disable-warnings flag, it appears that pytest happily collects all the warnings, stats them, etc; it just doesn't print them. In my case, that meant that pytest spent 85% of its time computing information that it immediately discarded.
The os.stat() check occurs inside Python's linecache.py function. Since I had an identical warning 3.6M times, I expected the function would run os.stat() once and cache the result, but that did not happen. I assume I'm just misunderstanding something basic about the intended use of this function.

How to get rid of pytest warnings

When I run my pytest in pipenv shell I get this:
pipenv shell
Loading .env environment variables…
Launching subshell in virtual environment…
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ . /Users/.../.local/share/virtualenvs/kittycapital-UOiJxZhy/bin/activate
(kittycapital) bash-3.2$ python -m pytest
============================================================================================================================= test session starts ==============================================================================================================================
platform darwin -- Python 3.7.7, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /Users/.../kittycapital
plugins: mock-3.1.1
collected 4 items
tests/test_account.py . [ 25%]
tests/test_pair.py .. [ 75%]
tests/helpers/test_number_helpers.py . [100%]
=============================================================================================================================== warnings summary ===============================================================================================================================
/Users/.../.local/share/virtualenvs/kittycapital-UOiJxZhy/lib/python3.7/site-packages/urllib3/util/selectors.py:14
/Users/.../.local/share/virtualenvs/kittycapital-UOiJxZhy/lib/python3.7/site-packages/urllib3/util/selectors.py:14: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
from collections import namedtuple, Mapping
/Users/.../.local/share/virtualenvs/kittycapital-UOiJxZhy/lib/python3.7/site-packages/urllib3/_collections.py:2
/Users/.../.local/share/virtualenvs/kittycapital-UOiJxZhy/lib/python3.7/site-packages/urllib3/_collections.py:2: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
from collections import Mapping, MutableMapping
-- Docs: https://docs.pytest.org/en/latest/warnings.html
How do I get rid of these warnings?
Either upgrade your dependencies to versions that do not trigger warnings, or put this in pytest.ini to hide that warning:
[pytest]
filterwarnings = ignore:.*Using or importing the ABCs.*is deprecated:DeprecationWarning
See https://docs.pytest.org/en/stable/warnings.html#deprecationwarning-and-pendingdeprecationwarning
Or use the --disable-warnings flag to hide all warnings:
python -m pytest --disable-warnings
See https://docs.pytest.org/en/stable/warnings.html#disabling-warnings-summary

pytest - Suppress DeprecationWarning from specific 3rd party modules

When I run pytest I'm getting some deprecation warnings from a 3rd party library. I'd like to be informed about any deprecation warnings in my own code, but not in a vendored copy of a library bundled with another 3rd-party library.
This answer was helpful in getting me partway there. If I run pytest like this:
$ pytest ./tests/ I get:
$ pytest ./tests/
============================= test session starts ==============================
platform linux -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
rootdir: /home/whlt/repos/tj-image-resizer/tests, inifile: pytest.ini
collected 5 items
tests/test_file1.py . [ 20%]
tests/test_file2.py .... [100%]
=============================== warnings summary ===============================
/home/whlt/.local/lib/python3.7/site-packages/botocore/vendored/requests/packages/urllib3/_collections.py:1
/home/whlt/.local/lib/python3.7/site-packages/botocore/vendored/requests/packages/urllib3/_collections.py:1
/home/whlt/.local/lib/python3.7/site-packages/botocore/vendored/requests/packages/urllib3/_collections.py:1: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import Mapping, MutableMapping
-- Docs: https://docs.pytest.org/en/latest/warnings.html
======================== 5 passed, 2 warnings in 2.54s =========================
but if I run pytest like this: $ pytest ./tests/ -W ignore::DeprecationWarning I get:
============================= test session starts ==============================
platform linux -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
rootdir: /home/whlt/repos/tj-image-resizer/tests, inifile: pytest.ini
collected 5 items
tests/test_file1.py . [ 20%]
tests/test_file2.py .... [100%]
============================== 5 passed in 2.61s ===============================
This second output shows me that the filter works, but that will also hide any deprecation warnings I'd like to seeing resulting from my own code.
Part of this issue is that I'm not sure which module to try referencing in the ignore filter. I've tried $ pytest ./tests/ -W ignore::DeprecationWarning:urllib3.*: and I've tried $ pytest ./tests/ -W ignore::DeprecationWarning:botocore.*:. Both of these result in the same output as the first example with no filtering.
How can I filter out DeprecationWarnings from the version of urllib3 packaged with the vendored version of requests included with botocore (which gets called when I run commands with the boto3 library)?
You should use the warning filters options (ini or marks):
[pytest]
filterwarnings =
ignore::DeprecationWarning:botocore.*:
Source: https://docs.python.org/3/library/warnings.html#default-warning-filter
"Individual warnings filters are specified as a sequence of fields separated by colons:"
action:message:category:module:line
The answer from #Santiago Magariños does not work for me (but it put me on the correct path to find solution - so many thanks).
I use Python 3.9, pytest 6.2.1 and trying to suppress warnings from selenium 3.141.0.
I have realized that I need to prepend .* before the module name:
[pytest]
filterwarnings = ignore:::.*.selenium
or use the full "path". So to suppress the warning
../../../../../../.local/share/virtualenvs/common-bjARi2zp/lib/python3.9/site-packages/selenium/webdriver/support/wait.py:28
/home/vaclav/.local/share/virtualenvs/common-bjARi2zp/lib/python3.9/site-packages/selenium/webdriver/support/wait.py:28: DeprecationWarning: invalid escape sequence \
"""Constructor, takes a WebDriver instance and timeout in seconds.
I need to use this filter in pytest.ini file:
[pytest]
filterwarnings = ignore:::.home.vaclav..local.share.virtualenvs.common-bjARi2zp.lib.python3.9.site-packages.selenium
if you are using pyproject.toml file for pytest configuration you can use:
[tool.pytest.ini_options]
testpaths = ["./tests/unit"]
filterwarnings = ["ignore:::.*third_party_package.module:123", "ignore:::.*another_module*"]
ignore:::.*third_party_package.module:123 ignores in specific warning at specific line
ignore:::.*another_module* ignores all warnings in the module.
Notice that you can have multiple ignores. You need to list them in []. Also, you can't have *third_party_package/module:123 you must replace all / with .

ImportError: No module named Binary with pytest

I'm working through http://blog.thedigitalcatonline.com/blog/2015/05/13/python-oop-tdd-example-part1/#.Vw0NojFJJ9n .
When I try:
$ py.test
============================= test session starts =============================
platform win32 -- Python 3.2.5, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: C:\envs\r3\binary, inifile:
plugins: capturelog-0.7
collected 0 items / 1 errors
=================================== ERRORS ====================================
____________________ ERROR collecting tests/test_binary.py ____________________
tests\test_binary.py:3: in <module>
import Binary
E ImportError: No module named Binary
================= 1 pytest-warnings, 1 error in 0.20 seconds ==================
What am I doing wrong?
Add current directory to PYTHONPATH environmental variable.
As you are on Windows:
$ set PYTHONPATH="."
This shall help py.test to find and import the module.
Checking the py.test tutorial I see, that at "Writing the class" section they use exactly the same trick.
In practice, you do not have to do this, as you usually test against installed Python module (typically with setup.py in project root directory and using develop mode), and it is accessible for import easily without playing with PYTHONPATH.

Categories

Resources