@@ -289,7 +289,6 @@ def _test():
289
289
'run_docstring_examples' ,
290
290
'is_private' ,
291
291
'Tester' ,
292
- 'DocTestTestFailure' ,
293
292
'DocTestSuite' ,
294
293
'testsource' ,
295
294
'debug' ,
@@ -1289,66 +1288,92 @@ def _find_tests(module, prefix=None):
1289
1288
_extract_doctests (mdict .items (), module , mdict , tests , prefix )
1290
1289
return tests
1291
1290
1292
- # unittest helpers.
1291
+ ###############################################################################
1292
+ # unitest support
1293
1293
1294
- # A function passed to unittest, for unittest to drive.
1295
- # tester is doctest Tester instance. doc is the docstring whose
1296
- # doctests are to be run.
1294
+ from StringIO import StringIO
1295
+ import os
1296
+ import sys
1297
+ import tempfile
1298
+ import unittest
1297
1299
1298
- def _utest (tester , name , doc , filename , lineno ):
1299
- import sys
1300
- from StringIO import StringIO
1300
+ class DocTestTestCase (unittest .TestCase ):
1301
+ """A test case that wraps a test function.
1301
1302
1302
- old = sys .stdout
1303
- sys .stdout = new = StringIO ()
1304
- try :
1305
- failures , tries = tester .runstring (doc , name )
1306
- finally :
1307
- sys .stdout = old
1308
-
1309
- if failures :
1310
- msg = new .getvalue ()
1311
- lname = '.' .join (name .split ('.' )[- 1 :])
1312
- if not lineno :
1313
- lineno = "0 (don't know line number)"
1314
- # Don't change this format! It was designed so that Emacs can
1315
- # parse it naturally.
1316
- raise DocTestTestFailure ('Failed doctest test for %s\n '
1317
- ' File "%s", line %s, in %s\n \n %s' %
1318
- (name , filename , lineno , lname , msg ))
1319
-
1320
- class DocTestTestFailure (Exception ):
1321
- """A doctest test failed"""
1322
-
1323
- def DocTestSuite (module = None ):
1324
- """Convert doctest tests for a module to a unittest TestSuite.
1325
-
1326
- The returned TestSuite is to be run by the unittest framework, and
1327
- runs each doctest in the module. If any of the doctests fail,
1328
- then the synthesized unit test fails, and an error is raised showing
1329
- the name of the file containing the test and a (sometimes approximate)
1330
- line number.
1331
-
1332
- The optional module argument provides the module to be tested. It
1333
- can be a module object or a (possibly dotted) module name. If not
1334
- specified, the module calling DocTestSuite() is used.
1335
-
1336
- Example (although note that unittest supplies many ways to use the
1337
- TestSuite returned; see the unittest docs):
1338
-
1339
- import unittest
1340
- import doctest
1341
- import my_module_with_doctests
1342
-
1343
- suite = doctest.DocTestSuite(my_module_with_doctests)
1344
- runner = unittest.TextTestRunner()
1345
- runner.run(suite)
1303
+ This is useful for slipping pre-existing test functions into the
1304
+ PyUnit framework. Optionally, set-up and tidy-up functions can be
1305
+ supplied. As with TestCase, the tidy-up ('tearDown') function will
1306
+ always be called if the set-up ('setUp') function ran successfully.
1346
1307
"""
1347
1308
1348
- import unittest
1309
+ def __init__ (self , tester , name , doc , filename , lineno ,
1310
+ setUp = None , tearDown = None ):
1311
+ unittest .TestCase .__init__ (self )
1312
+ (self .__tester , self .__name , self .__doc ,
1313
+ self .__filename , self .__lineno ,
1314
+ self .__setUp , self .__tearDown
1315
+ ) = tester , name , doc , filename , lineno , setUp , tearDown
1316
+
1317
+ def setUp (self ):
1318
+ if self .__setUp is not None :
1319
+ self .__setUp ()
1320
+
1321
+ def tearDown (self ):
1322
+ if self .__tearDown is not None :
1323
+ self .__tearDown ()
1324
+
1325
+ def runTest (self ):
1326
+ old = sys .stdout
1327
+ new = StringIO ()
1328
+ try :
1329
+ sys .stdout = new
1330
+ failures , tries = self .__tester .runstring (self .__doc , self .__name )
1331
+ finally :
1332
+ sys .stdout = old
1333
+
1334
+ if failures :
1335
+ lname = '.' .join (self .__name .split ('.' )[- 1 :])
1336
+ lineno = self .__lineno or "0 (don't know line no)"
1337
+ raise self .failureException (
1338
+ 'Failed doctest test for %s\n '
1339
+ ' File "%s", line %s, in %s\n \n %s'
1340
+ % (self .__name , self .__filename , lineno , lname , new .getvalue ())
1341
+ )
1342
+
1343
+ def id (self ):
1344
+ return self .__name
1345
+
1346
+ def __repr__ (self ):
1347
+ name = self .__name .split ('.' )
1348
+ return "%s (%s)" % (name [- 1 ], '.' .join (name [:- 1 ]))
1349
+
1350
+ __str__ = __repr__
1351
+
1352
+ def shortDescription (self ):
1353
+ return "Doctest: " + self .__name
1354
+
1355
+
1356
+ def DocTestSuite (module = None ,
1357
+ setUp = lambda : None ,
1358
+ tearDown = lambda : None ,
1359
+ ):
1360
+ """Convert doctest tests for a mudule to a unittest test suite
1361
+
1362
+ This tests convers each documentation string in a module that
1363
+ contains doctest tests to a unittest test case. If any of the
1364
+ tests in a doc string fail, then the test case fails. An error is
1365
+ raised showing the name of the file containing the test and a
1366
+ (sometimes approximate) line number.
1367
+
1368
+ A module argument provides the module to be tested. The argument
1369
+ can be either a module or a module name.
1370
+
1371
+ If no argument is given, the calling module is used.
1372
+
1373
+ """
1374
+ module = _normalizeModule (module )
1375
+ tests = _findTests (module )
1349
1376
1350
- module = _normalize_module (module )
1351
- tests = _find_tests (module )
1352
1377
if not tests :
1353
1378
raise ValueError (module , "has no tests" )
1354
1379
@@ -1362,78 +1387,166 @@ def DocTestSuite(module=None):
1362
1387
filename = filename [:- 1 ]
1363
1388
elif filename .endswith (".pyo" ):
1364
1389
filename = filename [:- 1 ]
1365
- def runit ( name = name , doc = doc , filename = filename , lineno = lineno ):
1366
- _utest ( tester , name , doc , filename , lineno )
1367
- suite . addTest ( unittest . FunctionTestCase (
1368
- runit ,
1369
- description = "doctest of " + name ))
1390
+
1391
+ suite . addTest ( DocTestTestCase (
1392
+ tester , name , doc , filename , lineno ,
1393
+ setUp , tearDown ))
1394
+
1370
1395
return suite
1371
1396
1372
- # Debugging support.
1397
+ def _normalizeModule (module ):
1398
+ # Normalize a module
1399
+ if module is None :
1400
+ # Test the calling module
1401
+ module = sys ._getframe (2 ).f_globals ['__name__' ]
1402
+ module = sys .modules [module ]
1403
+
1404
+ elif isinstance (module , (str , unicode )):
1405
+ module = __import__ (module , globals (), locals (), ["*" ])
1406
+
1407
+ return module
1408
+
1409
+ def _doc (name , object , tests , prefix , filename = '' , lineno = '' ):
1410
+ doc = getattr (object , '__doc__' , '' )
1411
+ if doc and doc .find ('>>>' ) >= 0 :
1412
+ tests .append ((prefix + name , doc , filename , lineno ))
1413
+
1414
+
1415
+ def _findTests (module , prefix = None ):
1416
+ if prefix is None :
1417
+ prefix = module .__name__
1418
+ dict = module .__dict__
1419
+ tests = []
1420
+ _doc (prefix , module , tests , '' ,
1421
+ lineno = "1 (or below)" )
1422
+ prefix = prefix and (prefix + "." )
1423
+ _find (dict .items (), module , dict , tests , prefix )
1424
+ return tests
1425
+
1426
+ def _find (items , module , dict , tests , prefix , minlineno = 0 ):
1427
+ for name , object in items :
1428
+
1429
+ # Only interested in named objects
1430
+ if not hasattr (object , '__name__' ):
1431
+ continue
1432
+
1433
+ if hasattr (object , 'func_globals' ):
1434
+ # Looks like a func
1435
+ if object .func_globals is not dict :
1436
+ # Non-local func
1437
+ continue
1438
+ code = getattr (object , 'func_code' , None )
1439
+ filename = getattr (code , 'co_filename' , '' )
1440
+ lineno = getattr (code , 'co_firstlineno' , - 1 ) + 1
1441
+ if minlineno :
1442
+ minlineno = min (lineno , minlineno )
1443
+ else :
1444
+ minlineno = lineno
1445
+ _doc (name , object , tests , prefix , filename , lineno )
1446
+
1447
+ elif hasattr (object , "__module__" ):
1448
+ # Maybe a class-like things. In which case, we care
1449
+ if object .__module__ != module .__name__ :
1450
+ continue # not the same module
1451
+ if not (hasattr (object , '__dict__' )
1452
+ and hasattr (object , '__bases__' )):
1453
+ continue # not a class
1454
+
1455
+ lineno = _find (object .__dict__ .items (), module , dict , tests ,
1456
+ prefix + name + "." )
1457
+
1458
+ _doc (name , object , tests , prefix ,
1459
+ lineno = "%s (or above)" % (lineno - 3 ))
1460
+
1461
+ return minlineno
1462
+
1463
+ # end unitest support
1464
+ ###############################################################################
1465
+
1466
+ ###############################################################################
1467
+ # debugger
1373
1468
1374
1469
def _expect (expect ):
1375
- # Return the expected output (if any), formatted as a Python
1376
- # comment block.
1470
+ # Return the expected output, if any
1377
1471
if expect :
1378
1472
expect = "\n # " .join (expect .split ("\n " ))
1379
1473
expect = "\n # Expect:\n # %s" % expect
1380
1474
return expect
1381
1475
1382
1476
def testsource (module , name ):
1383
- """Extract the doctest examples from a docstring.
1477
+ """Extract the test sources from a doctest test docstring as a script
1384
1478
1385
1479
Provide the module (or dotted name of the module) containing the
1386
- tests to be extracted, and the name (within the module) of the object
1387
- with the docstring containing the tests to be extracted .
1480
+ test to be debugged and the name (within the module) of the object
1481
+ with the doc string with tests to be debugged .
1388
1482
1389
- The doctest examples are returned as a string containing Python
1390
- code. The expected output blocks in the examples are converted
1391
- to Python comments.
1392
1483
"""
1393
-
1394
- module = _normalize_module (module )
1395
- tests = _find_tests (module , "" )
1396
- test = [doc for (tname , doc , dummy , dummy ) in tests
1397
- if tname == name ]
1484
+ module = _normalizeModule (module )
1485
+ tests = _findTests (module , "" )
1486
+ test = [doc for (tname , doc , f , l ) in tests if tname == name ]
1398
1487
if not test :
1399
1488
raise ValueError (name , "not found in tests" )
1400
1489
test = test [0 ]
1401
- examples = [source + _expect (expect )
1402
- for source , expect , dummy in _extract_examples (test )]
1403
- return '\n ' .join (examples )
1404
-
1405
- def debug (module , name ):
1406
- """Debug a single docstring containing doctests.
1407
-
1408
- Provide the module (or dotted name of the module) containing the
1409
- docstring to be debugged, and the name (within the module) of the
1410
- object with the docstring to be debugged.
1411
-
1412
- The doctest examples are extracted (see function testsource()),
1413
- and written to a temp file. The Python debugger (pdb) is then
1414
- invoked on that file.
1490
+ # XXX we rely on an internal doctest function:
1491
+ examples = _extract_examples (test )
1492
+ testsrc = '\n ' .join ([
1493
+ "%s%s" % (source , _expect (expect ))
1494
+ for (source , expect , lineno ) in examples
1495
+ ])
1496
+ return testsrc
1497
+
1498
+ def debug_src (src , pm = False , globs = None ):
1499
+ """Debug a single doctest test doc string
1500
+
1501
+ The string is provided directly
1415
1502
"""
1416
-
1417
- import os
1503
+ # XXX we rely on an internal doctest function:
1504
+ examples = _extract_examples (src )
1505
+ src = '\n ' .join ([
1506
+ "%s%s" % (source , _expect (expect ))
1507
+ for (source , expect , lineno ) in examples
1508
+ ])
1509
+ debug_script (src , pm , globs )
1510
+
1511
+ def debug_script (src , pm = False , globs = None ):
1512
+ "Debug a test script"
1418
1513
import pdb
1419
- import tempfile
1420
1514
1421
- module = _normalize_module (module )
1422
- testsrc = testsource (module , name )
1423
1515
srcfilename = tempfile .mktemp ("doctestdebug.py" )
1424
- f = file (srcfilename , 'w' )
1425
- f .write (testsrc )
1426
- f .close ()
1516
+ open (srcfilename , 'w' ).write (src )
1517
+ if globs :
1518
+ globs = globs .copy ()
1519
+ else :
1520
+ globs = {}
1427
1521
1428
- globs = {}
1429
- globs .update (module .__dict__ )
1430
1522
try :
1431
- # Note that %r is vital here. '%s' instead can, e.g., cause
1432
- # backslashes to get treated as metacharacters on Windows.
1433
- pdb .run ("execfile(%r)" % srcfilename , globs , globs )
1523
+ if pm :
1524
+ try :
1525
+ execfile (srcfilename , globs , globs )
1526
+ except :
1527
+ print sys .exc_info ()[1 ]
1528
+ pdb .post_mortem (sys .exc_info ()[2 ])
1529
+ else :
1530
+ # Note that %r is vital here. '%s' instead can, e.g., cause
1531
+ # backslashes to get treated as metacharacters on Windows.
1532
+ pdb .run ("execfile(%r)" % srcfilename , globs , globs )
1434
1533
finally :
1435
1534
os .remove (srcfilename )
1436
1535
1536
+ def debug (module , name , pm = False ):
1537
+ """Debug a single doctest test doc string
1538
+
1539
+ Provide the module (or dotted name of the module) containing the
1540
+ test to be debugged and the name (within the module) of the object
1541
+ with the doc string with tests to be debugged.
1542
+
1543
+ """
1544
+ module = _normalizeModule (module )
1545
+ testsrc = testsource (module , name )
1546
+ debug_script (testsrc , pm , module .__dict__ )
1547
+
1548
+ # end debugger
1549
+ ###############################################################################
1437
1550
1438
1551
1439
1552
class _TestClass :
0 commit comments