@@ -833,6 +833,118 @@ def test_empty_namespace_package(self):
833833 self .assertEqual (len (include_empty_finder .find (mod )), 1 )
834834 self .assertEqual (len (exclude_empty_finder .find (mod )), 0 )
835835
836+ def test_lineno_of_test_dict_strings (self ):
837+ """Test line numbers are found for __test__ dict strings."""
838+ module_content = '''\
839+ """Module docstring."""
840+
841+ def dummy_function():
842+ """Dummy function docstring."""
843+ pass
844+
845+ __test__ = {
846+ 'test_string': """
847+ This is a test string.
848+ >>> 1 + 1
849+ 2
850+ """,
851+ }
852+ '''
853+ with tempfile .TemporaryDirectory () as tmpdir :
854+ module_path = os .path .join (tmpdir , 'test_module_lineno.py' )
855+ with open (module_path , 'w' ) as f :
856+ f .write (module_content )
857+
858+ sys .path .insert (0 , tmpdir )
859+ try :
860+ import test_module_lineno
861+ finder = doctest .DocTestFinder ()
862+ tests = finder .find (test_module_lineno )
863+
864+ test_dict_test = None
865+ for test in tests :
866+ if '__test__' in test .name :
867+ test_dict_test = test
868+ break
869+
870+ self .assertIsNotNone (
871+ test_dict_test ,
872+ "__test__ dict test not found"
873+ )
874+ # gh-69113: line number should not be None for __test__ strings
875+ self .assertIsNotNone (
876+ test_dict_test .lineno ,
877+ "Line number should not be None for __test__ dict strings"
878+ )
879+ self .assertGreater (
880+ test_dict_test .lineno ,
881+ 0 ,
882+ "Line number should be positive"
883+ )
884+ finally :
885+ if 'test_module_lineno' in sys .modules :
886+ del sys .modules ['test_module_lineno' ]
887+ sys .path .pop (0 )
888+
889+ def test_lineno_multiline_matching (self ):
890+ """Test multi-line matching when no unique line exists."""
891+ # gh-69113: test that line numbers are found even when lines
892+ # appear multiple times (e.g., ">>> x = 1" in both test entries)
893+ module_content = '''\
894+ """Module docstring."""
895+
896+ __test__ = {
897+ 'test_one': """
898+ >>> x = 1
899+ >>> x
900+ 1
901+ """,
902+ 'test_two': """
903+ >>> x = 1
904+ >>> x
905+ 2
906+ """,
907+ }
908+ '''
909+ with tempfile .TemporaryDirectory () as tmpdir :
910+ module_path = os .path .join (tmpdir , 'test_module_multiline.py' )
911+ with open (module_path , 'w' ) as f :
912+ f .write (module_content )
913+
914+ sys .path .insert (0 , tmpdir )
915+ try :
916+ import test_module_multiline
917+ finder = doctest .DocTestFinder ()
918+ tests = finder .find (test_module_multiline )
919+
920+ test_one = None
921+ test_two = None
922+ for test in tests :
923+ if 'test_one' in test .name :
924+ test_one = test
925+ elif 'test_two' in test .name :
926+ test_two = test
927+
928+ self .assertIsNotNone (test_one , "test_one not found" )
929+ self .assertIsNotNone (test_two , "test_two not found" )
930+ self .assertIsNotNone (
931+ test_one .lineno ,
932+ "Line number should not be None for test_one"
933+ )
934+ self .assertIsNotNone (
935+ test_two .lineno ,
936+ "Line number should not be None for test_two"
937+ )
938+ self .assertNotEqual (
939+ test_one .lineno ,
940+ test_two .lineno ,
941+ "test_one and test_two should have different line numbers"
942+ )
943+ finally :
944+ if 'test_module_multiline' in sys .modules :
945+ del sys .modules ['test_module_multiline' ]
946+ sys .path .pop (0 )
947+
836948def test_DocTestParser (): r"""
837949Unit tests for the `DocTestParser` class.
838950
@@ -2434,7 +2546,8 @@ def test_DocTestSuite_errors():
24342546 <BLANKLINE>
24352547 >>> print(result.failures[1][1]) # doctest: +ELLIPSIS
24362548 Traceback (most recent call last):
2437- File "...sample_doctest_errors.py", line None, in test.test_doctest.sample_doctest_errors.__test__.bad
2549+ File "...sample_doctest_errors.py", line 37, in test.test_doctest.sample_doctest_errors.__test__.bad
2550+ >...>> 2 + 2
24382551 AssertionError: Failed example:
24392552 2 + 2
24402553 Expected:
@@ -2464,7 +2577,8 @@ def test_DocTestSuite_errors():
24642577 <BLANKLINE>
24652578 >>> print(result.errors[1][1]) # doctest: +ELLIPSIS
24662579 Traceback (most recent call last):
2467- File "...sample_doctest_errors.py", line None, in test.test_doctest.sample_doctest_errors.__test__.bad
2580+ File "...sample_doctest_errors.py", line 39, in test.test_doctest.sample_doctest_errors.__test__.bad
2581+ >...>> 1/0
24682582 File "<doctest test.test_doctest.sample_doctest_errors.__test__.bad[1]>", line 1, in <module>
24692583 1/0
24702584 ~^~
@@ -3256,15 +3370,15 @@ def test_testmod_errors(): r"""
32563370 ~^~
32573371 ZeroDivisionError: division by zero
32583372 **********************************************************************
3259- File "...sample_doctest_errors.py", line ? , in test.test_doctest.sample_doctest_errors.__test__.bad
3373+ File "...sample_doctest_errors.py", line 37 , in test.test_doctest.sample_doctest_errors.__test__.bad
32603374 Failed example:
32613375 2 + 2
32623376 Expected:
32633377 5
32643378 Got:
32653379 4
32663380 **********************************************************************
3267- File "...sample_doctest_errors.py", line ? , in test.test_doctest.sample_doctest_errors.__test__.bad
3381+ File "...sample_doctest_errors.py", line 39 , in test.test_doctest.sample_doctest_errors.__test__.bad
32683382 Failed example:
32693383 1/0
32703384 Exception raised:
0 commit comments