55import os
66from doctest import UnexpectedException
77
8+ from _pytest .config import hookimpl
9+
810try :
911 from builtins import breakpoint # noqa
1012
@@ -28,6 +30,12 @@ def pytest_addoption(parser):
2830 help = "start a custom interactive Python debugger on errors. "
2931 "For example: --pdbcls=IPython.terminal.debugger:TerminalPdb" ,
3032 )
33+ group ._addoption (
34+ "--trace" ,
35+ dest = "trace" ,
36+ action = "store_true" ,
37+ help = "Immediately break when running each test." ,
38+ )
3139
3240
3341def pytest_configure (config ):
@@ -38,6 +46,8 @@ def pytest_configure(config):
3846 else :
3947 pdb_cls = pdb .Pdb
4048
49+ if config .getvalue ("trace" ):
50+ config .pluginmanager .register (PdbTrace (), "pdbtrace" )
4151 if config .getvalue ("usepdb" ):
4252 config .pluginmanager .register (PdbInvoke (), "pdbinvoke" )
4353
@@ -71,7 +81,7 @@ class pytestPDB(object):
7181 _pdb_cls = pdb .Pdb
7282
7383 @classmethod
74- def set_trace (cls ):
84+ def set_trace (cls , set_break = True ):
7585 """ invoke PDB set_trace debugging, dropping any IO capturing. """
7686 import _pytest .config
7787
@@ -84,7 +94,8 @@ def set_trace(cls):
8494 tw .line ()
8595 tw .sep (">" , "PDB set_trace (IO-capturing turned off)" )
8696 cls ._pluginmanager .hook .pytest_enter_pdb (config = cls ._config )
87- cls ._pdb_cls ().set_trace (frame )
97+ if set_break :
98+ cls ._pdb_cls ().set_trace (frame )
8899
89100
90101class PdbInvoke (object ):
@@ -104,6 +115,30 @@ def pytest_internalerror(self, excrepr, excinfo):
104115 post_mortem (tb )
105116
106117
118+ class PdbTrace (object ):
119+ @hookimpl (hookwrapper = True )
120+ def pytest_pyfunc_call (self , pyfuncitem ):
121+ _test_pytest_function (pyfuncitem )
122+ yield
123+
124+
125+ def _test_pytest_function (pyfuncitem ):
126+ pytestPDB .set_trace (set_break = False )
127+ testfunction = pyfuncitem .obj
128+ pyfuncitem .obj = pdb .runcall
129+ if pyfuncitem ._isyieldedfunction ():
130+ arg_list = list (pyfuncitem ._args )
131+ arg_list .insert (0 , testfunction )
132+ pyfuncitem ._args = tuple (arg_list )
133+ else :
134+ if "func" in pyfuncitem ._fixtureinfo .argnames :
135+ raise ValueError ("--trace can't be used with a fixture named func!" )
136+ pyfuncitem .funcargs ["func" ] = testfunction
137+ new_list = list (pyfuncitem ._fixtureinfo .argnames )
138+ new_list .append ("func" )
139+ pyfuncitem ._fixtureinfo .argnames = tuple (new_list )
140+
141+
107142def _enter_pdb (node , excinfo , rep ):
108143 # XXX we re-use the TerminalReporter's terminalwriter
109144 # because this seems to avoid some encoding related troubles
0 commit comments