~launchpad-pqm/launchpad/devel

9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
1
#!${buildout:executable}
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
2
#
3
# Copyright 2009 Canonical Ltd.  This software is licensed under the
4
# GNU Affero General Public License version 3 (see the file LICENSE).
5
6
"""
7
Given an error report, run all of the failed tests again.
8
9
For instance, it can be used in the following scenario:
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
10
11
  % bin/test -vvm lp.registry | tee test.out
12
  % # Oh nos!  Failures!
13
  % # Fix tests.
9609.1.2 by Gavin Panella
Correct docstring to refer to new location of retest script.
14
  % bin/retest test.out
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
15
16
Or, when run without arguments (or if any argument is "-"), a test
17
report (or a part of) can be piped in, for example by pasting it:
18
9609.1.2 by Gavin Panella
Correct docstring to refer to new location of retest script.
19
  % bin/retest
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
20
  Tests with failures:
21
     lib/lp/registry/browser/tests/sourcepackage-views.txt
22
     lib/lp/registry/tests/../stories/product/xx-product-package-pages.txt
23
  Total: ... tests, 2 failures, 0 errors in ...
24
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
25
"""
26
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
27
import fileinput
28
import os
29
import re
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
30
import sys
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
31
from itertools import takewhile
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
32
from pprint import pprint
33
10713.1.1 by Gary Poster
use new version of z3c.recipe.filetemplate and zc.buildout fork to use relative paths.
34
${python-relative-path-setup}
9570.5.2 by Brad Crittenden
Minor changes from review.
35
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
36
# The test script for this branch.
11090.3.14 by Brad Crittenden
Fix retest to handle windmill tests.
37
TEST = "${buildout:directory/bin/test}"
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
38
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
39
# Regular expression to match numbered stories.
40
STORY_RE = re.compile("(.*)/\d{2}-.*")
41
42
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
43
def get_test_name(test):
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
44
    """Get the test name of a failed test.
45
46
    If the test is part of a numbered story,
47
    e.g. 'stories/gpg-coc/01-claimgpgp.txt', then return the directory name
48
    since all of the stories must be run together.
49
    """
50
    match = STORY_RE.match(test)
51
    if match:
52
        return match.group(1)
53
54
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
55
def gen_test_lines(lines):
56
    def p_start(line):
12060.2.1 by Gavin Panella
Make bin/retest work on errors too.
57
        return (
58
            line.startswith('Tests with failures:') or
59
            line.startswith('Tests with errors:'))
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
60
    def p_take(line):
12060.2.2 by Gavin Panella
Make bin/retest work when there are both errors and failures.
61
        return not (
62
            line.isspace() or
63
            line.startswith('Total:'))
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
64
    lines = iter(lines)
65
    for line in lines:
66
        if p_start(line):
67
            for line in takewhile(p_take, lines):
68
                yield line
69
70
71
def gen_tests(test_lines):
72
    for test_line in test_lines:
73
        yield get_test_name(test_line.strip())
74
75
76
def extract_tests(lines):
77
    return set(gen_tests(gen_test_lines(lines)))
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
78
79
80
def run_tests(tests):
81
    """Given a set of tests, run them as one group."""
82
    print "Running tests:"
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
83
    pprint(sorted(tests))
84
    args = ['-vv']
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
85
    for test in tests:
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
86
        args.append('-t')
87
        args.append(test)
88
    os.execl(TEST, TEST, *args)
9570.5.1 by Brad Crittenden
Added retest.py, a tool for re-running a failed set of tests based as listed in the output from a previous test run.
89
90
91
if __name__ == '__main__':
9609.1.1 by Gavin Panella
Merge retest improvements from mucked-up branch.
92
    tests = extract_tests(fileinput.input())
93
    if len(tests) >= 1:
94
        run_tests(tests)
95
    else:
96
        sys.stdout.write(
97
            "Error: no tests found\n"
98
            "Usage: %s [test_output_file|-] ...\n\n%s\n\n" % (
99
                sys.argv[0], __doc__.strip()))
100
        sys.exit(1)