Sharad
Sharad

Reputation: 10622

Is there a pytest command line option/plug-in for on-demand debugging (pdb)?

py.test --pdb supports dropping to pdb shell, on failure. Is there a way to drop to pdb shell, immediately after starting pytest and then setup a breakpoint (say based on a method name). The use-case is that I don't want to check-out/modify the code and add a break-point. I'd like to add it on-the-fly.

Python supports this: python -mpdb foo.py

sharad# ls
foo.py
sharad# cat foo.py 
def foo():
    print("hello")
    print("foo")
def bar():
    print("hello")
    print("bar")
foo()
bar()
sharad# python -mpdb foo.py 
> /home/sharad/foo.py(1)<module>()
-> def foo():
(Pdb) b bar
Breakpoint 1 at /home/sharad/foo.py:4
(Pdb) c
hello
foo
> /home/sharad/foo.py(5)bar()
-> print("hello")
(Pdb) n
hello
> /home/sharad/foo.py(6)bar()
-> print("bar")
(Pdb) n
bar

Any inputs/help will be appreciated!

Regards Sharad

Updated the question:

@tobyodavies: Thanks!. It triggers pdb but crashes later.
1. py.test throws an error with this invocation.

Sample test:
-----------
sharad# cat test_foo.py 
def test_foo():
    print("This is foo")
sharad# 

pdb with python
---------------
sharad# python -mpdb test_foo.py 
> /home/ssingla/trials/dynamic-debugger/test_foo.py(1)<module>()
-> def test_foo():
(Pdb) b test_foo.test_foo
Breakpoint 1 at /home/ssingla/trials/dynamic-debugger/test_foo.py:1
(Pdb) c
The program finished and will be restarted
> /home/ssingla/trials/dynamic-debugger/test_foo.py(1)<module>()
-> def test_foo():
(Pdb) 
sharad# 

pdb with python and py.test
---------------------------

sharad# python -mpdb $(which py.test) test_foo.py 
> /home/ssingla/trials/trial_env/bin/py.test(4)<module>()
-> import re
(Pdb) b test_foo.test_foo
*** The specified object 'test_foo.test_foo' is not a function or was not found along sys.path.
(Pdb) import sys
(Pdb) sys.path.append('.')
(Pdb) b test_foo.test_foo
Breakpoint 1 at /home/ssingla/trials/dynamic-debugger/test_foo.py:1
(Pdb) c
========================================================================================================= test session starts ==========================================================================================================
platform linux -- Python 3.5.1, pytest-2.8.7, py-1.4.31, pluggy-0.3.1
rootdir: /home/ssingla/trials/dynamic-debugger, inifile: 
plugins: cov-2.2.1, variables-1.3, instafail-0.3.0, timeout-1.0.0
collected 1 items 

test_foo.py F

=============================================================================================================== FAILURES ===============================================================================================================
_______________________________________________________________________________________________________________ test_foo _______________________________________________________________________________________________________________

    def test_foo():
>       print("This is foo")

test_foo.py:2: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
test_foo.py:2: in test_foo
    print("This is foo")
/usr/lib/python3.5/bdb.py:48: in trace_dispatch
    return self.dispatch_line(frame)
/usr/lib/python3.5/bdb.py:66: in dispatch_line
    self.user_line(frame)
/usr/lib/python3.5/pdb.py:259: in user_line
    self.interaction(frame, None)
/usr/lib/python3.5/pdb.py:346: in interaction
    self._cmdloop()
/usr/lib/python3.5/pdb.py:319: in _cmdloop
    self.cmdloop()
/usr/lib/python3.5/cmd.py:126: in cmdloop
    line = input(self.prompt)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_pytest.capture.DontReadFromInput object at 0x7f773d48d9e8>, args = ()

    def read(self, *args):
>       raise IOError("reading from stdin while output is captured")
E       OSError: reading from stdin while output is captured

../trial_env/lib/python3.5/site-packages/_pytest/capture.py:433: OSError
--------------------------------------------------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------------------------------------------------
> /home/ssingla/trials/dynamic-debugger/test_foo.py(2)test_foo()
-> print("This is foo")
(Pdb) 
======================================================================================================= 1 failed in 0.18 seconds =======================================================================================================
The program exited via sys.exit(). Exit status: 1
> /home/ssingla/trials/trial_env/bin/py.test(4)<module>()
-> import re
(Pdb) 

2. I am able to insert a breakpoint when the file containing the test code
   isn't in a nested directory structure.

sharad# PYTHONPATH=$PWD:$PWD/bar:$PYTHONPATH python -mpdb $(which py.test) bar/test_bar.py 
> /home/ssingla/trials/trials_env/bin/py.test(4)<module>()
-> import re
(Pdb) b bar.test_bar.test_bar
*** The specified object 'bar.test_bar.test_bar' is not a function or was not found along sys.path.
(Pdb) 
*** The specified object 'bar.test_bar.test_bar' is not a function or was not found along sys.path.
(Pdb) from bar.test_bar import test_bar
(Pdb) b test_bar
Breakpoint 1 at /home/ssingla/trials/dynamic-debugger/bar/test_bar.py:1
(Pdb) 

Upvotes: 0

Views: 526

Answers (1)

tobyodavies
tobyodavies

Reputation: 28099

What you want to do is to run pytest under pdb, and it appears you already know how to do that:

python -mpdb $(which pytest)

Upvotes: 1

Related Questions