Ticket #5787: usage-error.patch

File usage-error.patch, 7.1 KB (added by Julian Berman, 8 years ago)
  • twisted/scripts/trial.py

    diff --git a/twisted/scripts/trial.py b/twisted/scripts/trial.py
    index 32a2835..2afa4b9 100644
    a b def _reporterAction(): 
    102102                               plugin.getPlugins(itrial.IReporter)])
    103103
    104104
     105def _maybeFindSourceLine(testThing):
     106    """
     107    Try to find the source line of the given test thing.
     108
     109
     110    @param testThing: a test method or class
     111    @rtype: int
     112    @return: the starting source line, or -1 if one couldn't be found
     113    """
     114
     115    method = getattr(testThing, "_testMethodName", None)
     116    if method is not None:
     117        testThing = getattr(testThing, method)
     118
     119    # If it's a function, we can get the line number even if the source file no
     120    # longer exists
     121    code = getattr(testThing, "func_code", None)
     122    if code is not None:
     123        _, startLine = next(dis.findlinestarts(code))
     124        return startLine
     125
     126    try:
     127        return inspect.getsourcelines(testThing)[1]
     128    except (IOError, TypeError):
     129        # either testThing is a module, which raised a TypeError, or the file
     130        # couldn't be read
     131        return -1
     132
    105133
    106134# orders which can be passed to trial --order
    107 _runOrders = [
    108     ("alphabetical",
    109      "alphabetical order for test methods, arbitrary order for test cases"),
    110     ("toptobottom",
    111      "attempt to run test cases and methods in the order they were defined"),
    112 ]
     135_runOrders = {
     136    "alphabetical" : (
     137        "alphabetical order for test methods, arbitrary order for test cases",
     138        runner.name),
     139    "toptobottom" : (
     140     "attempt to run test cases and methods in the order they were defined",
     141     _maybeFindSourceLine),
     142}
     143
     144
     145def _coerceOrder(order):
     146    """
     147    Check that the given order is a known test running order.
     148
     149    Does nothing else, since looking up the appropriate callable to sort the
     150    tests should be done when it actually will be used, as the default argument
     151    will not be coerced by this function.
     152
     153    @param order: one of the known orders in L{_runOrders}
     154    @return: the order unmodified
     155    """
     156    if order not in _runOrders:
     157        raise usage.UsageError(
     158            "--order must be one of: %s. See --help-orders for details" %
     159            ", ".join(repr(order) for order in _runOrders))
     160    return order
    113161
    114162
    115163
    class _BasicOptions(object): 
    137185                ]
    138186
    139187    optParameters = [
    140         ["order", "o", None, "Specify what order to run test cases and methods"
    141          ". See --help-orders for more info."],
     188        ["order", "o", "alphabetical",
     189         "Specify what order to run test cases and methods. "
     190         "See --help-orders for more info.", _coerceOrder],
    142191        ["random", "z", None,
    143192         "Run tests in random order using the specified seed"],
    144193        ['temp-directory', None, '_trial_temp',
    class _BasicOptions(object): 
    148197         'more info.']]
    149198
    150199    compData = usage.Completions(
    151         optActions={"order": usage.CompleteList(
    152                         name for name, _ in _runOrders),
     200        optActions={"order": usage.CompleteList(_runOrders),
    153201                    "reporter": _reporterAction,
    154202                    "logfile": usage.CompleteFiles(descr="log file name"),
    155203                    "random": usage.Completer(descr="random seed")},
    class _BasicOptions(object): 
    226274                    "following options using --order=<foo>.\n")
    227275
    228276        print(synopsis)
    229         for name, description in _runOrders:
     277        for name, (description, _) in sorted(_runOrders.items()):
    230278            print('   ', name, '\t', description)
    231279        sys.exit(0)
    232280
    class _BasicOptions(object): 
    262310                "tbformat must be 'plain', 'emacs', or 'cgitb'.")
    263311
    264312
    265     def opt_order(self, order):
    266         """
    267         Run the tests in the given order.
    268 
    269         @param order: a test ordering
    270         """
    271 
    272         if order == "toptobottom":
    273             self['order'] = _maybeFindSourceLine
    274         elif order == "alphabetical":
    275             self['order'] = runner.name
    276         else:
    277             orders = ", ".join(repr(order) for order, _ in _runOrders)
    278             raise usage.UsageError("order must be one of " + orders)
    279 
    280 
    281313    def opt_recursionlimit(self, arg):
    282314        """
    283315        see sys.setrecursionlimit()
    def _getSuite(config): 
    453485
    454486
    455487
    456 def _maybeFindSourceLine(thing):
    457     """
    458     Try to find the source line of the given test thing.
    459 
    460 
    461     @param testThing: a test method or class
    462     @rtype: int
    463     @return: the starting source line, or -1 if one couldn't be found
    464     """
    465 
    466     method = getattr(thing, "_testMethodName", None)
    467     if method is not None:
    468         thing = getattr(thing, method)
    469 
    470     # If it's a function, we can get the line number even if the source file no
    471     # longer exists
    472     code = getattr(thing, "func_code", None)
    473     if code is not None:
    474         _, startLine = next(dis.findlinestarts(code))
    475         return startLine
    476 
    477     try:
    478         return inspect.getsourcelines(thing)[1]
    479     except (IOError, TypeError):
    480         # either thing is a module, which raised a TypeError, or the file
    481         # couldn't be read
    482         return -1
    483 
    484 
    485 
    486488def _getLoader(config):
    487489    loader = runner.TestLoader()
    488490    if config['random']:
    def _getLoader(config): 
    491493        loader.sorter = lambda x : randomer.random()
    492494        print('Running tests shuffled with seed %d\n' % config['random'])
    493495    elif config['order']:
    494         loader.sorter = config['order']
     496        _, sorter = _runOrders[config['order']]
     497        loader.sorter = sorter
    495498    if not config['until-failure']:
    496499        loader.suiteFactory = runner.DestructiveTestSuite
    497500    return loader
  • twisted/trial/test/test_script.py

    diff --git a/twisted/trial/test/test_script.py b/twisted/trial/test/test_script.py
    index aa03550..59c1a73 100644
    a b class OrderTests(unittest.TestCase): 
    747747        suite = loader.loadByNames(self.config['tests'])
    748748
    749749        names = testNames(suite)
     750        # twisted.trial.test.test_module, so split and key on the first 4 to
     751        # get stable alphabetical sort on those
    750752        self.assertEqual(
    751             names, sorted(names, key=lambda name : name.partition(".")[0]),
     753            names, sorted(names, key=lambda name : name.split(".")[:4]),
    752754        )
    753755
    754756
    class OrderTests(unittest.TestCase): 
    790792            'twisted_toptobottom_temp.test_missing.TestMissing.test_first'])
    791793
    792794
     795    def test_unknownOrder(self):
     796        """
     797        An unknown order passed to --order raises a L{UsageError}.
     798        """
     799
     800        self.assertRaises(
     801            UsageError, self.config.parseOptions, ["--order", "I don't exist"])
     802
     803
    793804
    794805class HelpOrderTests(unittest.TestCase):
    795806    """
    class HelpOrderTests(unittest.TestCase): 
    806817
    807818        trial.Options().parseOptions(["--help-orders"])
    808819
    809         for orderName, orderDesc in trial._runOrders:
     820        for orderName, (orderDesc, _) in trial._runOrders.items():
    810821            match = re.search(
    811822                "{0}.*{1}".format(orderName, orderDesc), sys.stdout.getvalue(),
    812823            )