[Zope3-checkins] SVN: zope.testing/trunk/src/zope/testing/ add profiling support with test

Benji York benji at zope.com
Wed Aug 24 13:32:25 EDT 2005


Log message for revision 38071:
  add profiling support with test
  (because of bug in 2.4.1 and earlier, only works when Python is run with -O)
  
  

Changed:
  A   zope.testing/trunk/src/zope/testing/profiling.txt
  U   zope.testing/trunk/src/zope/testing/testrunner.py

-=-
Added: zope.testing/trunk/src/zope/testing/profiling.txt
===================================================================
--- zope.testing/trunk/src/zope/testing/profiling.txt	2005-08-24 16:39:42 UTC (rev 38070)
+++ zope.testing/trunk/src/zope/testing/profiling.txt	2005-08-24 17:32:25 UTC (rev 38071)
@@ -0,0 +1,34 @@
+Profiling
+=========
+
+The testrunner includes the ability to profile the test execution with hotshot
+via the --profile option.
+
+    >>> import os.path, sys
+    >>> directory_with_tests = os.path.join(this_directory, 'testrunner-ex')
+    >>> sys.path.append(directory_with_tests)
+
+    >>> defaults = [
+    ...     '--path', directory_with_tests,
+    ...     '--tests-pattern', '^sampletestsf?$',
+    ...     ]
+
+    >>> sys.argv = 'test --profile'.split()
+
+When the tests are run, we get profiling output.
+
+    >>> from zope.testing import testrunner
+    >>> testrunner.run(defaults)
+    Running unit tests:
+    ...
+    Running samplelayers.Layer1 tests:
+    ...
+    Running samplelayers.Layer11 tests:
+    ...
+    Total: ... tests, 0 failures, 0 errors
+    ...
+       Ordered by: cumulative time, call count
+       List reduced from ... to 50 due to restriction <50>
+    <BLANKLINE>
+       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
+    ...


Property changes on: zope.testing/trunk/src/zope/testing/profiling.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: zope.testing/trunk/src/zope/testing/testrunner.py
===================================================================
--- zope.testing/trunk/src/zope/testing/testrunner.py	2005-08-24 16:39:42 UTC (rev 38070)
+++ zope.testing/trunk/src/zope/testing/testrunner.py	2005-08-24 17:32:25 UTC (rev 38071)
@@ -20,17 +20,21 @@
 # we want to use the latest, greatest doctest, which zope.testing
 # provides.  Then again, zope.testing is generally useful.
 import gc
+import glob
 import logging
 import optparse
 import os
 import pdb
 import re
 import sys
+import tempfile
+import threading
 import time
+import trace
 import traceback
-import threading
 import unittest
-import trace
+import hotshot
+import hotshot.stats
 
 real_pdb_set_trace = pdb.set_trace
 
@@ -101,6 +105,12 @@
     # to make tests of the test runner work properly. :)
     pdb.set_trace = real_pdb_set_trace
 
+    if options.profile and sys.version_info[:3] <= (2,4,1) and __debug__:
+        print ('Because of a bug in Python < 2.4.1, profiling '
+               'during tests requires the -O option be passed to '
+               'Python (not the test runner).')
+        sys.exit()
+
     if options.coverage:
         tracer = MyTrace(ignoredirs=[sys.prefix, sys.exec_prefix],
                          ignoremods=["os", "posixpath", "stat"],
@@ -110,14 +120,41 @@
         tracer = None
 
     try:
+        if options.profile:
+            prof_prefix = 'tests_profile'
+            prof_suffix = '.prof'
+            prof_glob = prof_prefix + '*' + prof_suffix
+            dummy, file_path = tempfile.mkstemp(prof_suffix, prof_prefix, '.')
+            prof = hotshot.Profile(file_path)
+            prof.start()
+
         try:
-            failed = run_with_options(options)
-        except EndRun:
-            failed = True
+            try:
+                failed = run_with_options(options)
+            except EndRun:
+                failed = True
+        finally:
+            if tracer:
+                tracer.stop()
+            if options.profile:                         
+                prof.stop()
+                prof.close()
+
+        if options.profile:
+            stats = None
+            for file_name in glob.glob(prof_glob):
+                loaded = hotshot.stats.load(file_name)
+                if stats is None:
+                    stats = loaded
+                else:
+                    stats.add(loaded)
+            stats.sort_stats('cumulative', 'calls')
+            stats.print_stats(50)
     finally:
-        if tracer:
-            tracer.stop()
-                                 
+        if options.profile:
+            for file_name in glob.glob(prof_glob):
+                os.unlink(file_name)
+
     if tracer:
         coverdir = os.path.join(os.getcwd(), options.coverage)
         r = tracer.results()
@@ -996,13 +1033,20 @@
 """)
 
 analysis.add_option(
-    '--coverage', action="store", dest='coverage',
+    '--coverage', action="store", type='string', dest='coverage',
     help="""\
 Perform code-coverage analysis, saving trace data to the directory
 with the given name.  A code coverage summary is printed to standard
 out.
 """)
 
+analysis.add_option(
+    '--profile', action="store_true", dest='profile',
+    help="""\
+Run the tests under hotshot and display the top 50 stats, sorted by
+cumulative time and number of calls.
+""")
+
 def do_pychecker(*args):
     if not os.environ.get("PYCHECKER"):
         os.environ["PYCHECKER"] = "-q"
@@ -1223,12 +1267,21 @@
     def tearDown(test):
         sys.path, sys.argv = test.globs['saved-sys-info']
 
-    return doctest.DocFileSuite('testrunner.txt', 'testrunner-edge-cases.txt',
-                                setUp=setUp, tearDown=tearDown,
-                                optionflags=doctest.ELLIPSIS
-                                            +doctest.NORMALIZE_WHITESPACE,
-                                checker=checker, )
+    suite = doctest.DocFileSuite(
+        'testrunner.txt', 'testrunner-edge-cases.txt',
+        setUp=setUp, tearDown=tearDown,
+        optionflags=doctest.ELLIPSIS+doctest.NORMALIZE_WHITESPACE,
+        checker=checker)
 
+    if not __debug__:
+        suite = unittest.TestSuite([suite, doctest.DocFileSuite(
+            'profiling.txt',
+            setUp=setUp, tearDown=tearDown,
+            optionflags=doctest.ELLIPSIS+doctest.NORMALIZE_WHITESPACE,
+            checker=checker)])
+
+    return suite
+
 def main():
     default = [
         '--path', os.path.split(sys.argv[0])[0],



More information about the Zope3-Checkins mailing list