@@ -576,7 +576,8 @@ def test_1():
576
576
child .sendline ("c" )
577
577
child .expect ("LEAVING RECURSIVE DEBUGGER" )
578
578
assert b"PDB continue" not in child .before
579
- assert b"print_from_foo" in child .before
579
+ # No extra newline.
580
+ assert child .before .endswith (b"c\r \n print_from_foo\r \n " )
580
581
child .sendline ("c" )
581
582
child .expect (r"PDB continue \(IO-capturing resumed\)" )
582
583
rest = child .read ().decode ("utf8" )
@@ -603,6 +604,98 @@ def test_1():
603
604
child .expect ("1 passed" )
604
605
self .flush (child )
605
606
607
+ @pytest .mark .parametrize ("capture_arg" , ("" , "-s" , "-p no:capture" ))
608
+ def test_pdb_continue_with_recursive_debug (self , capture_arg , testdir ):
609
+ """Full coverage for do_debug without capturing.
610
+
611
+ This is very similar to test_pdb_interaction_continue_recursive in general,
612
+ but mocks out ``pdb.set_trace`` for providing more coverage.
613
+ """
614
+ p1 = testdir .makepyfile (
615
+ """
616
+ try:
617
+ input = raw_input
618
+ except NameError:
619
+ pass
620
+
621
+ def set_trace():
622
+ __import__('pdb').set_trace()
623
+
624
+ def test_1(monkeypatch):
625
+ import _pytest.debugging
626
+
627
+ class pytestPDBTest(_pytest.debugging.pytestPDB):
628
+ @classmethod
629
+ def set_trace(cls, *args, **kwargs):
630
+ # Init _PdbWrapper to handle capturing.
631
+ _pdb = cls._init_pdb(*args, **kwargs)
632
+
633
+ # Mock out pdb.Pdb.do_continue.
634
+ import pdb
635
+ pdb.Pdb.do_continue = lambda self, arg: None
636
+
637
+ print("=== SET_TRACE ===")
638
+ assert input() == "debug set_trace()"
639
+
640
+ # Simulate _PdbWrapper.do_debug
641
+ cls._recursive_debug += 1
642
+ print("ENTERING RECURSIVE DEBUGGER")
643
+ print("=== SET_TRACE_2 ===")
644
+
645
+ assert input() == "c"
646
+ _pdb.do_continue("")
647
+ print("=== SET_TRACE_3 ===")
648
+
649
+ # Simulate _PdbWrapper.do_debug
650
+ print("LEAVING RECURSIVE DEBUGGER")
651
+ cls._recursive_debug -= 1
652
+
653
+ print("=== SET_TRACE_4 ===")
654
+ assert input() == "c"
655
+ _pdb.do_continue("")
656
+
657
+ def do_continue(self, arg):
658
+ print("=== do_continue")
659
+ # _PdbWrapper.do_continue("")
660
+
661
+ monkeypatch.setattr(_pytest.debugging, "pytestPDB", pytestPDBTest)
662
+
663
+ import pdb
664
+ monkeypatch.setattr(pdb, "set_trace", pytestPDBTest.set_trace)
665
+
666
+ set_trace()
667
+ """
668
+ )
669
+ child = testdir .spawn_pytest ("%s %s" % (p1 , capture_arg ))
670
+ child .expect ("=== SET_TRACE ===" )
671
+ before = child .before .decode ("utf8" )
672
+ if not capture_arg :
673
+ assert ">>> PDB set_trace (IO-capturing turned off) >>>" in before
674
+ else :
675
+ assert ">>> PDB set_trace >>>" in before
676
+ child .sendline ("debug set_trace()" )
677
+ child .expect ("=== SET_TRACE_2 ===" )
678
+ before = child .before .decode ("utf8" )
679
+ assert "\r \n ENTERING RECURSIVE DEBUGGER\r \n " in before
680
+ child .sendline ("c" )
681
+ child .expect ("=== SET_TRACE_3 ===" )
682
+
683
+ # No continue message with recursive debugging.
684
+ before = child .before .decode ("utf8" )
685
+ assert ">>> PDB continue " not in before
686
+
687
+ child .sendline ("c" )
688
+ child .expect ("=== SET_TRACE_4 ===" )
689
+ before = child .before .decode ("utf8" )
690
+ assert "\r \n LEAVING RECURSIVE DEBUGGER\r \n " in before
691
+ child .sendline ("c" )
692
+ rest = child .read ().decode ("utf8" )
693
+ if not capture_arg :
694
+ assert "> PDB continue (IO-capturing resumed) >" in rest
695
+ else :
696
+ assert "> PDB continue >" in rest
697
+ assert "1 passed in" in rest
698
+
606
699
def test_pdb_used_outside_test (self , testdir ):
607
700
p1 = testdir .makepyfile (
608
701
"""
@@ -970,3 +1063,52 @@ def test_2():
970
1063
rest = child .read ().decode ("utf8" )
971
1064
assert "no tests ran" in rest
972
1065
TestPDB .flush (child )
1066
+
1067
+
1068
+ @pytest .mark .parametrize ("fixture" , ("capfd" , "capsys" ))
1069
+ def test_pdb_suspends_fixture_capturing (testdir , fixture ):
1070
+ """Using "-s" with pytest should suspend/resume fixture capturing."""
1071
+ p1 = testdir .makepyfile (
1072
+ """
1073
+ def test_inner({fixture}):
1074
+ import sys
1075
+
1076
+ print("out_inner_before")
1077
+ sys.stderr.write("err_inner_before\\ n")
1078
+
1079
+ __import__("pdb").set_trace()
1080
+
1081
+ print("out_inner_after")
1082
+ sys.stderr.write("err_inner_after\\ n")
1083
+
1084
+ out, err = {fixture}.readouterr()
1085
+ assert out =="out_inner_before\\ nout_inner_after\\ n"
1086
+ assert err =="err_inner_before\\ nerr_inner_after\\ n"
1087
+ """ .format (
1088
+ fixture = fixture
1089
+ )
1090
+ )
1091
+
1092
+ child = testdir .spawn_pytest (str (p1 ) + " -s" )
1093
+
1094
+ child .expect ("Pdb" )
1095
+ before = child .before .decode ("utf8" )
1096
+ assert (
1097
+ "> PDB set_trace (IO-capturing turned off for fixture %s) >" % (fixture )
1098
+ in before
1099
+ )
1100
+
1101
+ # Test that capturing is really suspended.
1102
+ child .sendline ("p 40 + 2" )
1103
+ child .expect ("Pdb" )
1104
+ assert "\r \n 42\r \n " in child .before .decode ("utf8" )
1105
+
1106
+ child .sendline ("c" )
1107
+ rest = child .read ().decode ("utf8" )
1108
+ assert "out_inner" not in rest
1109
+ assert "err_inner" not in rest
1110
+
1111
+ TestPDB .flush (child )
1112
+ assert child .exitstatus == 0
1113
+ assert "= 1 passed in " in rest
1114
+ assert "> PDB continue (IO-capturing resumed for fixture %s) >" % (fixture ) in rest
0 commit comments