7 """Redirects sys.stdout to self and stores all that is written to it
11 """Initilalizes with an empty buffer
15 self
.original
= sys
.stdout
17 def write(self
, line
):
18 """Mandatory write method that stores the written line
23 def status(self
, line
):
24 """Prints a status line to stdout
26 This line is written to the true stdout even if stdout is redirected.
29 line: The line to be written to stdout.
32 self
.original
.write(line
)
34 def error(self
, line
):
35 """Prints an error line to stdout
37 This line is written to the true stdout even if stdout is redirected.
38 The line is prefix with \033[31m to make it show up in red on a terminal
39 and suffixed with \033[m to restore to regular color.
42 self
.original
.write("\033[31m" + line
+ "\033[m")
45 """Prints an success line to stdout
47 This line is written to the true stdout even if stdout is redirected.
48 The line is prefix with \033[32m to make it show up in green on a terminal
49 and suffixed with \033[m to restore to regular color.
52 self
.original
.write("\033[32m" + line
+ "\033[m")
55 """Restores sys.stdout to the original stdout
57 When created, or when catch is called, the current
58 sys.stdout is stored. Upon calling this method the
59 stored stdout is restored.
62 sys
.stdout
= self
.original
65 """Stores the current stdout and redirects it to self
68 self
.original
= sys
.stdout
72 """Returns all the output catched so far as one big string
75 return "".join(self
.buf
)
77 class GitResult(unittest
.TestResult
):
78 """A custom implementation to match Git's test suite's output style
81 def __init__(self
, output
, verbose
=False):
82 """Initializes all counters to zero
86 self
.shouldStop
= False
95 def writeError(self
, test
):
96 """Outputs an error message for the specified test
99 msg
= ("* FAIL %d: %s\n\t %s\n" %
100 (self
.test_count
, test
.shortDescription(), test
.__str
__()))
101 self
.output
.error(msg
)
103 def addError(self
, test
, err
):
105 self
.writeError(test
)
106 self
.output
.error("\t %s\n" % str(err
[1]))
108 def addFailure(self
, test
, err
):
109 self
.test_failure
+= 1
110 self
.writeError(test
)
111 self
.output
.error("\t %s\n" % str(err
[1]))
113 def addSuccess(self
, test
):
114 self
.test_success
+= 1
115 msg
= "* ok %d: %s\n" % (self
.test_count
, test
.shortDescription())
116 self
.output
.status(msg
)
118 def startTest(self
, test
):
119 # Check if the description is set
120 description
= test
.shortDescription()
122 raise TypeError("Description should be set")
126 print("* expecting success:")
127 print("\t" + test
.id())
129 def wasSuccessful(self
):
130 return not self
.test_failure
and not self
.test_error
133 """Prints a status line
136 if self
.wasSuccessful():
137 msg
= "* passed all %d test(s)\n" % self
.test_count
138 self
.output
.good(msg
)
141 if self
.test_failure
:
142 msg
+= "failed %d test(s)" % self
.test_failure
147 msg
+= "errored on %d test(s)" % self
.test_error
151 self
.output
.error(msg
)
154 """A test running class that makes use of GitResult to run the tests
157 def run(self
, test
, verbose
=False):
158 """Runs the specified test
162 catcher
= OutputCatcher()
169 # Set up a result object
170 result
= GitResult(catcher
, verbose
)
178 # Print the test results
183 def runTests(self
, options
, classes
):
184 """Runs the specified test in a test suite after parsing args
187 args: A list of arguments to parse, supported: -v/--verbose
188 tests: The tests to run
191 self
.verbose
= options
.verbose
193 # Create suites from the supplied classes
194 loader
= unittest
.defaultTestLoader
198 for testClass
in classes
:
199 suite
= loader
.loadTestsFromTestCase(testClass
)
202 # Create a suite for the tests
203 suite
= unittest
.TestSuite(suites
)
206 res
= self
.run(suite
, verbose
=self
.verbose
)
208 if res
.wasSuccessful():