[tor-commits] [bridgedb/master] Rewrite `python setyp.py test` code to run Trial tests only.

isis at torproject.org isis at torproject.org
Fri May 1 07:10:59 UTC 2015


commit 382a4f5e54a26dc7a2179d17cb4129f68e3e650e
Author: Isis Lovecruft <isis at torproject.org>
Date:   Thu Apr 16 04:23:24 2015 +0000

    Rewrite `python setyp.py test` code to run Trial tests only.
---
 lib/bridgedb/parse/options.py |   27 ----------
 lib/bridgedb/runner.py        |   47 ----------------
 setup.py                      |  119 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 109 insertions(+), 84 deletions(-)

diff --git a/lib/bridgedb/parse/options.py b/lib/bridgedb/parse/options.py
index 2ed93d0..3979615 100644
--- a/lib/bridgedb/parse/options.py
+++ b/lib/bridgedb/parse/options.py
@@ -251,32 +251,6 @@ class BaseOptions(usage.Options):
             print("  self['rundir']=%s" % self['rundir'])
 
 
-class TestOptions(BaseOptions):
-    """Suboptions for running twisted.trial and unittest based tests."""
-
-    longdesc = textwrap.dedent("""BridgeDB testing commands.
-    See the `bridgedb mock` command for generating testing environments.""")
-
-    optFlags = [['coverage', 'c', 'Generate coverage statistics']]
-    optParameters = [
-        ['file', 'f', None, 'Run tests in specific file(s) (trial only)'],
-        ['unittests', 'u', False, 'Run unittests in bridgedb.Tests'],
-        ['trial', 't', True, 'Run twisted.trial tests in bridgedb.test']]
-
-    completionData = usage.Completions(
-        mutuallyExclusive=[('unittests', 'coverage'),
-                           ('unittests', 'file')],
-        optActions={'file': usage.CompleteFiles('lib/bridgedb/test/test_*.py',
-                                                repeat=True,
-                                                descr="test filename")},
-        extraActions=[
-            usage.Completer(descr="extra arguments to pass to trial")])
-
-    def parseArgs(self, *args):
-        """Parse any additional arguments after the options and flags."""
-        self['test_args'] = args
-
-
 class MockOptions(BaseOptions):
     """Suboptions for creating necessary conditions for testing purposes."""
 
@@ -315,7 +289,6 @@ class MainOptions(BaseOptions):
         ['dump-bridges', 'd', 'Dump bridges by hashring assignment into files'],
         ['reload', 'R', 'Reload bridge descriptors into running servers']]
     subCommands = [
-        ['test', None, TestOptions, "Run twisted.trial tests or unittests"],
         ['mock', None, MockOptions, "Generate a testing environment"],
         ['SIGHUP', None, SIGHUPOptions,
          "Reload bridge descriptors into running servers"],
diff --git a/lib/bridgedb/runner.py b/lib/bridgedb/runner.py
index 7be7700..6ac069f 100644
--- a/lib/bridgedb/runner.py
+++ b/lib/bridgedb/runner.py
@@ -94,53 +94,6 @@ def generateDescriptors(count=None, rundir=None):
         del subprocess
         return statuscode
 
-def runTrial(options):
-    """Run Twisted trial based unittests, optionally with coverage.
-
-    :type options: :class:`~bridgedb.opt.TestOptions`
-    :param options: Parsed options for controlling the twisted.trial test
-        run. All unrecognised arguments after the known options will be passed
-        along to trial.
-    """
-    from twisted.scripts import trial
-
-    # Insert 'trial' as the first system cmdline argument:
-    sys.argv = ['trial']
-
-    if options['coverage']:
-        try:
-            from coverage import coverage
-        except ImportError as ie:
-            print(ie.message)
-        else:
-            cov = coverage()
-            cov.start()
-            sys.argv.append('--coverage')
-            sys.argv.append('--reporter=bwverbose')
-
-    # Pass all arguments along to its options parser:
-    if 'test_args' in options:
-        for arg in options['test_args']:
-            sys.argv.append(arg)
-    # Tell trial to test the bridgedb package:
-    sys.argv.append('bridgedb.test')
-    trial.run()
-
-    if options['coverage']:
-        cov.stop()
-        cov.html_report('_trial_temp/coverage/')
-
-def runTests(options):
-    """Run unittest based tests.
-
-    :type options: :class:`~bridgedb.opt.TestOptions`
-    :param options: Parsed options for controlling the twisted.trial test
-        run. All unrecognised arguments after the known options will be passed
-        along to trial.
-    """
-    testModule = __import__('bridgedb.Tests', globals(), '', [])
-    testModule.Tests.main()
-
 def doDumpBridges(config):
     """Dump bridges by assignment to a file.
 
diff --git a/setup.py b/setup.py
index 9402071..032aa10 100644
--- a/setup.py
+++ b/setup.py
@@ -74,6 +74,7 @@ install_i18n = os.path.join('bridgedb', 'i18n')
 # Directory to install docs, license, and other text resources into:
 install_docs = os.path.join('share', 'doc', 'bridgedb')
 
+
 def get_cmdclass():
     """Get our cmdclass dictionary for use in setuptool.setup().
 
@@ -81,7 +82,7 @@ def get_cmdclass():
     to add our own classes to the cmdclass dictionary, and then update that
     dictionary with the one returned from versioneer.get_cmdclass().
     """
-    cmdclass = {'test': runTests,
+    cmdclass = {'test': Trial,
                 'compile_catalog': compile_catalog,
                 'extract_messages': extract_messages,
                 'init_catalog': init_catalog,
@@ -238,15 +239,69 @@ def get_data_files(filesonly=False):
     return data_files
 
 
-class runTests(setuptools.Command):
-    # Based on setup.py from mixminion, which is based on setup.py
-    # from Zooko's pyutil package, which is in turn based on
-    # http://mail.python.org/pipermail/distutils-sig/2002-January/002714.html
-    description = "Run unit tests"
-    user_options = []
+class Trial(setuptools.Command):
+    """Twisted Trial setuptools command.
+
+    Based on the setuptools Trial command in Zooko's Tahoe-LAFS, as well as
+    https://github.com/simplegeo/setuptools-trial/ (which is also based on the
+    Tahoe-LAFS code).
+
+    Pieces of the original implementation of this 'test' command (that is, for
+    the original pyunit-based BridgeDB tests which, a long time ago, in a
+    galaxy far far away, lived in bridgedb.Tests) were based on setup.py from
+    Nick Mathewson's mixminion, which was based on the setup.py from Zooko's
+    pyutil package, which was in turn based on
+    http://mail.python.org/pipermail/distutils-sig/2002-January/002714.html.
+
+    Crusty, old-ass Python, like hella wut.
+    """
+    description = "Run Twisted Trial-based tests."
+    user_options = [
+        ('debug', 'b', ("Run tests in a debugger. If that debugger is pdb, will "
+                        "load '.pdbrc' from current directory if it exists.")),
+        ('debug-stacktraces', 'B', "Report Deferred creation and callback stack traces"),
+        ('debugger=', None, ("The fully qualified name of a debugger to use if "
+                             "--debug is passed (default: pdb)")),
+        ('disablegc', None, "Disable the garbage collector"),
+        ('force-gc', None, "Have Trial run gc.collect() before and after each test case"),
+        ('jobs=', 'j', "Number of local workers to run, a strictly positive integer"),
+        ('profile', None, "Run tests under the Python profiler"),
+        ('random=', 'Z', "Run tests in random order using the specified seed"),
+        ('reactor=', 'r', "Which reactor to use"),
+        ('reporter=', None, "Customize Trial's output with a reporter plugin"),
+        ('rterrors', 'e', "Realtime errors: print out tracebacks as soon as they occur"),
+        ('spew', None, "Print an insanely verbose log of everything that happens"),
+        ('testmodule=', None, "Filename to grep for test cases (-*- test-case-name)"),
+        ('tbformat=', None, ("Specify the format to display tracebacks with. Valid "
+                             "formats are 'plain', 'emacs', and 'cgitb' which uses "
+                             "the nicely verbose stdlib cgitb.text function")),
+        ('unclean-warnings', None, "Turn dirty reactor errors into warnings"),
+        ('until-failure', 'u', "Repeat a test (specified by -s) until it fails."),
+        ('without-module=', None, ("Fake the lack of the specified modules, separated "
+                                   "with commas")),
+    ]
+    boolean_options = ['debug', 'debug-stacktraces', 'disablegc', 'force-gc',
+                       'profile', 'rterrors', 'spew', 'unclean-warnings',
+                       'until-failure']
 
     def initialize_options(self):
-        pass
+        self.debug = None
+        self.debug_stacktraces = None
+        self.debugger = None
+        self.disablegc = None
+        self.force_gc = None
+        self.jobs = None
+        self.profile = None
+        self.random = None
+        self.reactor = None
+        self.reporter = None
+        self.rterrors = None
+        self.spew = None
+        self.testmodule = None
+        self.tbformat = None
+        self.unclean_warnings = None
+        self.until_failure = None
+        self.without_module = None
 
     def finalize_options(self):
         build = self.get_finalized_command('build')
@@ -257,11 +312,55 @@ class runTests(setuptools.Command):
         self.run_command('build')
         old_path = sys.path[:]
         sys.path[0:0] = [self.build_purelib, self.build_platlib]
+
+        result = 1
         try:
-            testmod = __import__("bridgedb.Tests", globals(), "", [])
-            testmod.Tests.main()
+            result = self.run_tests()
         finally:
             sys.path = old_path
+            raise SystemExit(result)
+
+    def run_tests(self):
+        # We do the import from Twisted inside the function instead of the top
+        # of the file because since Twisted is a setup_requires, we can't
+        # assume that Twisted will be installed on the user's system prior, so
+        # if we don't do the import here, then importing from this plugin will
+        # fail.
+        from twisted.scripts import trial
+
+        if not self.testmodule:
+            self.testmodule = "bridgedb.test"
+
+        # Handle parsing the trial options passed through the setuptools
+        # trial command.
+        cmd_options = []
+        for opt in self.boolean_options:
+            if getattr(self, opt.replace('-', '_'), None):
+                cmd_options.append('--%s' % opt)
+
+        for opt in ('debugger', 'jobs', 'random', 'reactor', 'reporter',
+                    'testmodule', 'tbformat', 'without-module'):
+            value = getattr(self, opt.replace('-', '_'), None)
+            if value is not None:
+                cmd_options.extend(['--%s' % opt, value])
+
+        config = trial.Options()
+        config.parseOptions(cmd_options)
+        config['tests'] = [self.testmodule,]
+
+        trial._initialDebugSetup(config)
+        trialRunner = trial._makeRunner(config)
+        suite = trial._getSuite(config)
+
+        # run the tests
+        if self.until_failure:
+            test_result = trialRunner.runUntilFailure(suite)
+        else:
+            test_result = trialRunner.run(suite)
+
+        if test_result.wasSuccessful():
+            return 0  # success
+        return 1      # failure
 
 
 # If there is an environment variable BRIDGEDB_INSTALL_DEPENDENCIES=0, it will





More information about the tor-commits mailing list