Skip to content

Commit

Permalink
Fixed skip report so it goes to stream. Added -k/--no-skip-report out…
Browse files Browse the repository at this point in the history
…put option to suppress the new skip report. Reordered the output options. Changed the behavior of -o/--omit-patterns to append patterns to the default list instead of replace the default list. Added -O/--clear-omit option to clear the default list. Got back to 100% test coverage.
  • Loading branch information
CleanCut committed Jun 25, 2015
1 parent aeaa355 commit fe8f5af
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 58 deletions.
97 changes: 57 additions & 40 deletions green/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,18 @@
termcolor = None,
notermcolor = None,
allow_stdout = False,
debug = 0,
no_skip_report = False,
help = False, # Not in configs
logging = False,
version = False,
logging = False,
debug = 0,
verbose = 1,
failfast = False,
config = None, # Not in configs
file_pattern = 'test*.py',
test_pattern = '*',
run_coverage = False,
clear_omit = False,
omit_patterns = None,
completion_file = False,
completions = False,
Expand Down Expand Up @@ -202,18 +204,23 @@ def parseArguments(): # pragma: no cover
help=("Instead of capturing the stdout and stderr and presenting it in "
"the summary of results, let it come through."),
default=argparse.SUPPRESS))
store_opt(out_args.add_argument('-d', '--debug', action='count',
help=("Enable internal debugging statements. Implies --logging. Can "
"be specified up to three times for more debug output."),
store_opt(out_args.add_argument('-k', '--no-skip-report',
action='store_true', help=("Don't print the report of skipped tests "
"after testing is done. Skips will still show up in the progress "
"report and summary count."),
default=argparse.SUPPRESS))
store_opt(out_args.add_argument('-h', '--help', action='store_true',
help="Show this help message and exit.",
default=argparse.SUPPRESS))
store_opt(out_args.add_argument('-V', '--version', action='store_true',
help="Print the version of Green and Python and exit.",
default=argparse.SUPPRESS))
store_opt(out_args.add_argument('-l', '--logging', action='store_true',
help="Don't configure the root logger to redirect to /dev/null, "
"enabling internal debugging output", default=argparse.SUPPRESS))
store_opt(out_args.add_argument('-V', '--version', action='store_true',
help="Print the version of Green and Python and exit.",
store_opt(out_args.add_argument('-d', '--debug', action='count',
help=("Enable internal debugging statements. Implies --logging. Can "
"be specified up to three times for more debug output."),
default=argparse.SUPPRESS))
store_opt(out_args.add_argument('-v', '--verbose', action='count',
help=("Verbose. Can be specified up to three times for more verbosity. "
Expand All @@ -239,11 +246,20 @@ def parseArguments(): # pragma: no cover
"Coverage Options ({})".format(coverage_version))
store_opt(cov_args.add_argument('-r', '--run-coverage', action='store_true',
help=("Produce coverage output."), default=argparse.SUPPRESS))
store_opt(cov_args.add_argument('-O', '--clear-omit', action='store_true',
help=("Green tries really hard to set up a good list of patterns of "
"files to omit from coverage reports. If the default list catches "
"files that you DO want to cover you can specify this flag to "
"leave the default list empty to start with. You can then add "
"patterns back in with --omit-add. The default list is something"
"like'*/test*,*/termstyle*,*/mock*,*(temp dir)*,*(python system "
"packages)*' -- only longer."),
default=argparse.SUPPRESS))
store_opt(cov_args.add_argument('-o', '--omit-patterns', action='store',
metavar='PATTERN',
help=("Comma-separated file-patterns to omit from coverage. Default "
"is something like '*/test*,*/termstyle*,*/mock*,*(temp "
"dir)*,*(python system packages)*'"),
help=("Comma-separated file-patterns to omit from coverage. For "
"example, if coverage reported a file mypackage/foo/bar you could"
"omit it from coverage with 'mypackage*', '*/foo/*', or '*bar'"),
default=argparse.SUPPRESS))

integration_args = parser.add_argument_group("Integration Options")
Expand Down Expand Up @@ -359,7 +375,8 @@ def mergeConfig(args, testing=False, coverage_testing=False): # pragma: no cover
Returns: I return a new argparse.Namespace, adding members:
shouldExit = default False
exitCode = default 0
omit_patterns = omit-patterns settings converted to list and extended
omit_patterns = omit-patterns settings converted to list and extended,
taking clear-omit into account.
cov = coverage object default None
"""
config = getConfig(getattr(args, 'config', default_args.config))
Expand All @@ -370,7 +387,7 @@ def mergeConfig(args, testing=False, coverage_testing=False): # pragma: no cover
config_getter = None
if name in ['html', 'termcolor', 'notermcolor', 'allow_stdout', 'help',
'logging', 'version', 'failfast', 'run_coverage', 'options',
'completions', 'completion_file']:
'completions', 'completion_file', 'clear_omit', 'no_skip_report']:
config_getter = config.getboolean
elif name in ['processes', 'debug', 'verbose']:
config_getter = config.getint
Expand Down Expand Up @@ -430,35 +447,35 @@ def mergeConfig(args, testing=False, coverage_testing=False): # pragma: no cover
# Coverage. We must enable it here because we cannot cover module-level
# code after it is imported, and this is the earliest place we can turn on
# coverage.
omit_patterns = []
omit_patterns = [
'*/argparse*',
'*/colorama*',
'*/django/*',
'*/distutils*', # Gets pulled in on Travis-CI CPython
'*/extras*', # pulled in by testtools
'*/linecache2*', # pulled in by testtools
'*/mimeparse*', # pulled in by testtools
'*/mock*',
'*/pbr*', # pulled in by testtools
'*/pkg_resources*', # pulled in by django
'*/pypy*',
'*/pytz*', # pulled in by django
'*/six*', # pulled in by testtools
'*/termstyle*',
'*/test*',
'*/traceback2*', # pulled in by testtools
'*/unittest2*', # pulled in by testtools
tempfile.gettempdir() + '*',
]
if 'green' not in new_args.targets and (
False in [t.startswith('green.') for t in new_args.targets]):
omit_patterns.extend([
'*Python.framework*',
'*site-packages*'])
if new_args.clear_omit:
omit_patterns = []
if new_args.omit_patterns:
omit_patterns = new_args.omit_patterns.split(',')
else:
omit_patterns = [
'*/argparse*',
'*/colorama*',
'*/django/*',
'*/distutils*', # Gets pulled in on Travis-CI CPython
'*/extras*', # pulled in by testtools
'*/linecache2*', # pulled in by testtools
'*/mimeparse*', # pulled in by testtools
'*/mock*',
'*/pbr*', # pulled in by testtools
'*/pkg_resources*', # pulled in by django
'*/pypy*',
'*/pytz*', # pulled in by django
'*/six*', # pulled in by testtools
'*/termstyle*',
'*/test*',
'*/traceback2*', # pulled in by testtools
'*/unittest2*', # pulled in by testtools
tempfile.gettempdir() + '*',
]
if 'green' not in new_args.targets and (
False in [t.startswith('green.') for t in new_args.targets]):
omit_patterns.extend([
'*Python.framework*',
'*site-packages*'])
omit_patterns.extend(new_args.omit_patterns.split(','))
new_args.omit_patterns = omit_patterns

if new_args.run_coverage:
Expand Down
34 changes: 18 additions & 16 deletions green/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ def __init__(self, args, stream):
super(GreenTestResult, self).__init__(
stream,
Colors(args.termcolor, args.html))
self.args = args
self.showAll = args.verbose > 1
self.dots = args.verbose == 1
self.verbose = args.verbose
Expand All @@ -251,32 +252,32 @@ def stop(self):
self.shouldStop = True


def tryRecordingStdoutStderr(self, ptr, test):
if ptr.stdout_output.get(test, False):
self.recordStdout(test, ptr.stdout_output[test])
if ptr.stderr_errput.get(test, False):
self.recordStderr(test, ptr.stderr_errput[test])
def tryRecordingStdoutStderr(self, test, proto_test_result):
if proto_test_result.stdout_output.get(test, False):
self.recordStdout(test, proto_test_result.stdout_output[test])
if proto_test_result.stderr_errput.get(test, False):
self.recordStderr(test, proto_test_result.stderr_errput[test])


def addProtoTestResult(self, proto_test_result):
for test, err in proto_test_result.errors:
self.addError(test, err)
self.tryRecordingStdoutStderr(proto_test_result, test)
self.tryRecordingStdoutStderr(test, proto_test_result)
for test, err in proto_test_result.expectedFailures:
self.addExpectedFailure(test, err)
self.tryRecordingStdoutStderr(proto_test_result, test)
self.tryRecordingStdoutStderr(test, proto_test_result)
for test, err in proto_test_result.failures:
self.addFailure(test, err)
self.tryRecordingStdoutStderr(proto_test_result, test)
self.tryRecordingStdoutStderr(test, proto_test_result)
for test in proto_test_result.passing:
self.addSuccess(test)
self.tryRecordingStdoutStderr(proto_test_result, test)
self.tryRecordingStdoutStderr(test, proto_test_result)
for test, reason in proto_test_result.skipped:
self.addSkip(test, reason)
self.tryRecordingStdoutStderr(proto_test_result, test)
self.tryRecordingStdoutStderr(test, proto_test_result)
for test in proto_test_result.unexpectedSuccesses:
self.addUnexpectedSuccess(test)
self.tryRecordingStdoutStderr(proto_test_result, test)
self.tryRecordingStdoutStderr(test, proto_test_result)


def startTestRun(self):
Expand Down Expand Up @@ -467,11 +468,12 @@ def printErrors(self):
self.stream.writeln()

# Skipped Test Report
for test, reason in self.skipped:
print("\n{} {} - {}".format(
self.colors.blue('Skipped'),
self.colors.bold(test.dotted_name),
reason))
if not self.args.no_skip_report:
for test, reason in self.skipped:
self.stream.writeln("\n{} {} - {}".format(
self.colors.blue('Skipped'),
self.colors.bold(test.dotted_name),
reason))

# Captured output for non-failing tests
failing_tests = set([x[0] for x in self.all_errors])
Expand Down
18 changes: 16 additions & 2 deletions green/test/test_cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def test_coverage(self):
"If coverage and --run-coverage, then coverage is started"
save_coverage = config.coverage
config.coverage = MagicMock()
config.sys.argv = ['', '--run-coverage', '--omit-patterns=abc']
config.sys.argv = ['', '--run-coverage', '--omit-patterns=abc', '--clear-omit']
cmdline.main(testing=True, coverage_testing=True)
config.coverage.coverage.assert_called_with(
data_file=u'.coverage', omit=['abc'])
Expand All @@ -150,6 +150,18 @@ def test_noTestsCreatesEmptyTestSuite(self):
cmdline.main(testing=True)


def test_omit_patterns_clear(self):
"Omit pattern gets parsed"
save_coverage = config.coverage
config.coverage = MagicMock()
cov = MagicMock()
config.coverage.coverage.return_value = cov
config.sys.argv = [
'', '--run-coverage', '--clear-omit', '--omit-patterns', 'a,b']
cmdline.main(testing=True, coverage_testing=True)
self.assertEqual(cov.report.mock_calls[0][2]['omit'], ['a', 'b'])
config.coverage = save_coverage

def test_omit_patterns(self):
"Omit pattern gets parsed"
save_coverage = config.coverage
Expand All @@ -158,7 +170,9 @@ def test_omit_patterns(self):
config.coverage.coverage.return_value = cov
config.sys.argv = ['', '--run-coverage', '--omit-patterns', 'a,b']
cmdline.main(testing=True, coverage_testing=True)
self.assertEqual(cov.report.mock_calls[0][2]['omit'], ['a', 'b'])
self.assertIn('a', cov.report.mock_calls[0][2]['omit'])
self.assertIn('b', cov.report.mock_calls[0][2]['omit'])
self.assertIn('*/colorama*', cov.report.mock_calls[0][2]['omit'])
config.coverage = save_coverage


Expand Down
75 changes: 75 additions & 0 deletions green/test/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,40 @@ def test_displayStdout(self):
self.assertIn(noise, stream.getvalue())


def test_stderrErrput(self):
"""
recordStderr records errput.
"""
btr = BaseTestResult(None, None)
pt = ProtoTest()
o = "some errput"
btr.recordStderr(pt, o)
self.assertEqual(btr.stderr_errput[pt], o)


def test_stderrNoErrput(self):
"""
recordStderr ignores empty errput sent to it
"""
btr = BaseTestResult(None, None)
pt = ProtoTest()
btr.recordStderr(pt, '')
self.assertEqual(btr.stderr_errput, {})


def test_displayStderr(self):
"""
displayStderr displays captured stderr
"""
stream = StringIO()
noise = "blah blah blah"
btr = BaseTestResult(stream, Colors(False, False))
pt = ProtoTest()
btr.stderr_errput[pt] = noise
btr.displayStderr(pt)
self.assertIn(noise, stream.getvalue())




class TestProtoTestResult(unittest.TestCase):
Expand Down Expand Up @@ -253,6 +287,33 @@ def tearDown(self):
del(self.args)


def test_tryRecordingStdoutStderr(self):
"""
Recording stdout and stderr works correctly.
"""
gtr = GreenTestResult(self.args, GreenStream(self.stream))
gtr.recordStdout = MagicMock()
gtr.recordStderr = MagicMock()

output = 'apple'
test1 = MagicMock()
ptr1 = MagicMock()
ptr1.stdout_output = {test1:output}
ptr1.stderr_errput = {}

errput = 'banana'
test2 = MagicMock()
ptr2 = MagicMock()
ptr2.stdout_output = {}
ptr2.stderr_errput = {test2:errput}


gtr.tryRecordingStdoutStderr(test1, ptr1)
gtr.recordStdout.assert_called_with(test1, output)
gtr.tryRecordingStdoutStderr(test2, ptr2)
gtr.recordStderr.assert_called_with(test2, errput)


def test_failfastAddError(self):
"""
addError triggers failfast when it is set
Expand Down Expand Up @@ -391,6 +452,20 @@ def test_method(self):
self.assertFalse('>' in self.stream.getvalue())


def test_printErrorsSkipreport(self):
"""
printErrors() prints the skip report
"""
self.args.verbose = 1
gtr = GreenTestResult(self.args, GreenStream(self.stream))
pt = MyProtoTest()
reason = "dog ate homework"
gtr.addSkip(pt, reason)
gtr.printErrors()
self.assertIn(reason, self.stream.getvalue())



def test_printErrorsStdout(self):
"""
printErrors() prints out the captured stdout
Expand Down

0 comments on commit fe8f5af

Please sign in to comment.