Debugging pytest post mortem exceptions in pycharm/pydev - python

I would like to use the built in Pytest runner of PyCharm together with the debugger without pre-configuring breakpoints.
The problem is that exceptions in my test are caught by Pytest so PyCharm's post mortem debugger cannot handle the exception.
I know using a breakpoint works but I would prefer not to run my test twice.
Found a way to do this in Unittest, I would like to know if something like this exists in Pytest.
Is there a way to catch unittest exceptions with PyCharm?

Are you using pytest-pycharm plugin? Looks like it works for me. Create virtualenv, pip install pytest pytest-pycharm, use this virtualenv at PyCharm Edit configuration -> Python Interpreter and then run with Debug ... Example:
import pytest
def test_me():
assert None
if __name__ == '__main__':
pytest.main(args=[__file__])
PyCharm debugger stops at assert None point, with (<class '_pytest.assertion.reinterpret.AssertionError'>, AssertionError(u'assert None',), None)
EDIT
Set Preferences > Tools > Python Integration Tools > Default test runner to py.test. Then Run > Debug 'py.test in test_me.py'

Related

Can't get PyTest to run in VSCode or terminal. No tests recognized

I have installed pytest using pip. Sample code below
import pytest
def example():
assert 9 == 9
My settings.json file looks like this
{
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.nosetestsEnabled": false,
"python.testing.pytestEnabled": true
}
I keep getting no tests ran in terminal when using the pytest filename.py command.
Python version : 3.9.1
pytest version : 6.2.2.
Anyone have any ideas?
Update: Jason's answer below is what worked. The problem was the naming of the file and methods. File name needed to end in '_test.py' for vscode to run tests and functions needed to start with 'test_' for both terminal and vscode to run.
Try renaming the file to "test_filename.py" and the test function to "test_example" so that they are detected by pytest.
https://docs.pytest.org/en/reorganize-docs/new-docs/user/naming_conventions.html
Also, a useful pytest option for debugging the ability to run tests is "--collect-only". It will attempt to only find tests without running them.
pytest --collect-only
VSCode has the ability to run tests itself, without you executing them in the terminal.
https://code.visualstudio.com/docs/python/testing

No tests collected by pytest

I have problem in importing pytest while writing a python code. "import pytest is grayed out.
Python is 3.8.3, Pycharm community edition.
pytest version 5.4.2, is successfully installed and can be seen in the project interpreter in pycharm. As well as I can see the installed path of pytest in python directory.
When running py.test command from console. It starts the test run shows "collected 0 items" and lastly ends with "NO TESTS RAN IN 0.05s"
If anyone running similar problems with some other packages kindly let me know.
TIA...
You simply run pytest from the commandline. There is no need to import pytest into a script. Take this Python script as an example:
def inc(x):
return x + 1
def test_answer():
assert inc(3) == 4
To run pytest on it, from the terminal (after changing to the right directory):
$ pytest
And you will then see the test outcome in the commandline as pytest automatically picks up the python scripts names test_*.py, where * is any name, e.g. test_increment.py. To have a test from your Python script run, name it with test_ as well to begin with.
Running pytest in the terminal is an option. In addition, Pycharm has integrated test suite for automatic discovery and collection of test tasks. You can use hotkey ctrl+shift+10 to run the test tasks directly in current file .

How to debug unittests with pudb debugger?

I am having some trouble trying to debug some unit tests through the pudb debugger.
The tests run fine with python, but I had no luck runnign them with pudb.
I isolated the problem, getting to the following sample code:
class Math:
def pow(self, x, y):
return x ** y
import unittest
class MathTest(unittest.TestCase):
def testPow23(self):
self.assertEquals(8, Math().pow(2, 3))
def testPow24(self):
self.assertEquals(16, Math().pow(2, 4))
if __name__ == '__main__':
unittest.main()
The tests run fine:
$ python amodule.py
.
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
But if running through pudb, it gives me the output:
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
I've tried running using pudb amodule.py and also with python -m pudb.run amodule.py, but it makes no difference -- no tests are run in one or another way.
Should I be doing something different to debug unit tests using pudb?
Try placing a breakpoint on a useful line in your code:
from pudb import set_trace; set_trace()
The ways you tried to launch it might interfere with test discovery and/or not run your script with a __name__ of '__main__'.
Since this is a popular question, I feel I should also mention that most test running tools will require you to pass in a switch to prevent it from capturing the standard output and input (usually it's -s).
So, remember to run pytest -s when using Pytest, or nosetests -s for Nose, python manage.py test -s for Django tests, or check the documentation for your test running tool.
You can set a breakpoint even easier by:
import pudb; pu.db

How to execute ipdb.set_trace() at will while running pytest tests

I'm using pytest for my test suite. While catching bugs in complex inter-components test, I would like to place import ipdb; ipdb.set_trace() in the middle of my code to allow me to debug it.
However, since pytest traps sys.stdin/sys.stdout ipdb fails. How can I use ipdb while testing with pytest.
I'm not interested in jumping to pdb or ipdb after a failure, but to place breaks anywhere in the code and be able to debug it there before the failure occurs.
The error is raised because pytest captures output by default.
You can run pytest with -s option (turn off capture output). For example:
py.test -s my_test.py
and then in my_test.py:
import ipdb;
ipdb.set_trace()
pytest-ipdb is unfortunately not supported anymore.
The solution is to run
pytest my_test.py --pdb --pdbcls=IPython.terminal.debugger:Pdb
From the help command:
pytest -h
--pdb start the interactive Python debugger on errors.
--pdbcls=modulename:classname
start a custom interactive Python debugger on errors.
For example:
--pdbcls=IPython.terminal.debugger:TerminalPdb
The difference is just that TerminalPdb seems to throw erros, but Pdb not (Ipython docs).
As of 2019-11 here is what should fix it:
pip install ipdb gnureadline ptpython
export PYTEST_ADDOPTS='--pdb --pdbcls=IPython.terminal.debugger:Pdb'
This is what I use
py.test tests/ --pdbcls=IPython.core.debugger:Pdb -s
You may want to give pdbpp a try. I've had more success with it, compared to ipdb when used with pytest. See my answer here: https://stackoverflow.com/a/69320311/2896799.

PyDev running pytest unit test with module-shared fixture fails

I have a problem running pytest unit tests with pyDev. I try to run a unit test with a module shared fixture and a finalizer which should be excecuted after the last test.
But when running the unit test in pyDev it does not use the same instance but instead creates two different instances. The example is running fine in the console or when started from a script within pydev.
I'm using platform Python 2.7.3, pytest-2.3.4, pyDev 2.7.3.2013031601, Eclipse 4.2 on Win7.
I tried the example from http://pytest.org/latest/fixture.html
The output from pydev is:
============================= test session starts ==============================
platform win32 -- Python 2.7.3 -- pytest-2.3.4
__________________________________ test_ehlo ___________________________________
smtp = <smtplib.SMTP instance at 0x027F9080>
__________________________________ test_noop ___________________________________
smtp = <smtplib.SMTP instance at 0x027FF3C8>
The console output is:
============================= test session starts ==============================
platform win32 -- Python 2.7.3 -- pytest-2.3.4
__________________________________ test_ehlo ___________________________________
smtp = <smtplib.SMTP instance at 0x01E51288>
__________________________________ test_noop ___________________________________
smtp = <smtplib.SMTP instance at 0x01E51288>
Which is the expected behaviour. What am I doing wrong??
the used code is conftest.py:
import pytest
import smtplib
#pytest.fixture(scope="module")
def smtp():
return smtplib.SMTP("merlinux.eu")
The test code in test_smtplib.py:
# content of test_module.py
def test_ehlo(smtp):
response = smtp.ehlo()
assert response[0] == 250
assert "merlinux" in response[1]
assert 0 # for demo purposes
def test_noop(smtp):
response = smtp.noop()
assert response[0] == 250
assert 0 # for demo purposes
Running the test from script with:
import pytest,os
os.chdir("[path_to_tests]/tests") #your file location
pytest.main(['-s', 'test_smtplib.py'])
Any suggestions and thanks a lot for your help!
I don't have eclipse but I've been looking through the source code for Pydev and pytest. pytest doesn't use multiprocessing by default but it will if you have xdist installed. Perhaps you have it? Or perhaps Eclipse has installed it?
If you still have the system available, can you try setting the option below in your pytest parameters? It simply tells pytest to use one process when using xdist as documented here.
-n=1 or perhaps it will prefer -n 1
If that doesn't work, then this also shouldn't work but could you try it? Use the option below in the pytest options as before (not in the pydev test runner options) to enable module-level testing. It's a pydev test runner option so I guess it will cause an error, but maybe some other code that keys off the option will make use of it.
--split_jobs=module or again perhaps --split_jobs module
Seems like this is a long-standing bug on the pydev side. I just fixed it and submitted a pull request to Pydev, see https://github.com/fabioz/Pydev/pull/120 . In the meanwhile, you could probably take out the little change and apply to your installed version of pydev, enabling proper pydev/pytest runs with scoping.

Categories

Resources