Back to index

python-biopython  1.60
test_Tutorial.py
Go to the documentation of this file.
00001 import unittest
00002 import doctest
00003 import os
00004 import sys
00005 
00006 if sys.version_info[0] >= 3:
00007     from lib2to3 import refactor
00008     rt = refactor.RefactoringTool(refactor.get_fixers_from_package("lib2to3.fixes"))
00009     assert rt.refactor_docstring(">>> print 2+2\n4\n", "example") == \
00010            ">>> print(2+2)\n4\n"
00011     
00012 tutorial = os.path.join(os.path.dirname(sys.argv[0]), "../Doc/Tutorial.tex")
00013 tutorial_base = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../Doc/"))
00014 original_path = os.path.abspath(".")
00015 
00016 def _extract(handle):
00017     line = handle.readline()
00018     if line != "\\begin{verbatim}\n":
00019         raise ValueError("Any '%doctest' or '%cont-doctest' line should be followed by '\\begin{verbatim}'")
00020     lines = []
00021     while True:
00022         line = handle.readline()
00023         if not line:
00024             if lines:
00025                 print "".join(lines[:30])
00026                 raise ValueError("Didn't find end of test starting: %r", lines[0])
00027             else:
00028                 raise ValueError("Didn't find end of test!")
00029         elif line.startswith("\end{verbatim}"):
00030             break
00031         else:
00032             lines.append(line)
00033     return lines
00034     
00035 def extract_doctests(latex_filename):
00036     """Scans LaTeX file and pulls out marked doctests as strings."""
00037     handle = open(latex_filename, "rU")
00038     line_number = 0
00039     in_test = False
00040     lines = []
00041     while True:
00042         line = handle.readline()
00043         line_number += 1
00044         if not line:
00045             #End of file
00046             break
00047         elif line.startswith("%cont-doctest"):
00048             x = _extract(handle)
00049             lines.extend(x)
00050             line_number += len(x) + 2
00051         elif line.startswith("%doctest"):
00052             if lines:
00053                 if not lines[0].startswith(">>> "):
00054                     raise ValueError("Should start '>>> ' not %r" % lines[0])
00055                 yield name, "".join(lines), folder
00056                 lines = []
00057             try:
00058                 folder = line.split(None,1)[1].strip()
00059             except:
00060                 folder = ""
00061             name = "test_from_line_%05i" % line_number
00062             x = _extract(handle)
00063             lines.extend(x)
00064             line_number += len(x) + 2
00065     handle.close()
00066     if lines:
00067         if not lines[0].startswith(">>> "):
00068             raise ValueError("Should start '>>> ' not %r" % lines[0])
00069         yield name, "".join(lines), folder
00070     #yield "dummy", ">>> 2 + 2\n5\n"
00071 
00072 class TutorialDocTestHolder(object):
00073     """Python doctests extracted from the Biopython Tutorial."""
00074     pass
00075 
00076 
00077 #Create dummy methods on the object purely to hold doctests
00078 for name, example, folder in extract_doctests(tutorial):
00079     if sys.version_info[0] >= 3:
00080         example = rt.refactor_docstring(example, name)
00081     def funct(n, d, f):
00082         global tutorial_base
00083         method = lambda x : None
00084         if f:
00085             p = os.path.join(tutorial_base, f)
00086             method.__doc__ = "%s\n\n>>> import os\n>>> os.chdir(%r)\n%s\n" \
00087                            % (n, p, d)
00088         else:
00089             method.__doc__ = "%s\n\n%s\n" % (n, d)
00090         method._folder = f
00091         return method
00092     setattr(TutorialDocTestHolder,
00093             "doctest_%s" % name.replace(" ","_"),
00094             funct(name, example, folder))
00095     del funct
00096 
00097 
00098 #This is a TestCase class so it is found by run_tests.py
00099 class TutorialTestCase(unittest.TestCase):
00100     """Python doctests extracted from the Biopython Tutorial."""
00101     #Single method to be invoked by run_tests.py
00102     def test_doctests(self):
00103         """Run tutorial doctests."""
00104         runner = doctest.DocTestRunner()
00105         failures = []
00106         for test in doctest.DocTestFinder().find(TutorialDocTestHolder):
00107             failed, success = runner.run(test)
00108             if failed:
00109                 name = test.name
00110                 assert name.startswith("TutorialDocTestHolder.doctest_")
00111                 failures.append(name[30:])
00112                 #raise ValueError("Tutorial doctest %s failed" % test.name[30:])
00113         if failures:
00114             raise ValueError("%i Tutorial doctests failed: %s" % \
00115                              (len(failures), ", ".join(failures)))
00116 
00117     def tearDown(self):
00118         global original_path
00119         os.chdir(original_path)
00120 
00121 
00122 #This is to run the doctests if the script is called directly:
00123 if __name__ == "__main__":
00124     print "Runing Tutorial doctests..."
00125     import doctest
00126     tests = doctest.testmod()
00127     if tests[0]:
00128         #Note on Python 2.5+ can use tests.failed rather than tests[0]
00129         raise RuntimeError("%i/%i tests failed" % tests)
00130     print "Tests done"