Skip to content

Commit

Permalink
Support 'skip' feature of newer unittest
Browse files Browse the repository at this point in the history
  • Loading branch information
multani committed May 7, 2013
1 parent f82d5ce commit c9a45e3
Show file tree
Hide file tree
Showing 30 changed files with 453 additions and 233 deletions.
88 changes: 71 additions & 17 deletions src/zope/testrunner/formatter.py
Expand Up @@ -165,17 +165,20 @@ def format_seconds_short(self, n_seconds):
"""Format a time in seconds (short version)."""
return "%.3f s" % n_seconds

def summary(self, n_tests, n_failures, n_errors, n_seconds):
def summary(self, n_tests, n_failures, n_errors, n_seconds,
n_skipped=0):
"""Summarize the results of a single test layer."""
print((" Ran %s tests with %s failures and %s errors in %s."
% (n_tests, n_failures, n_errors,
self.format_seconds(n_seconds))))
print (" Ran %s tests with %s failures, %s errors and "
"%s skipped in %s."
% (n_tests, n_failures, n_errors, n_skipped,
self.format_seconds(n_seconds)))

def totals(self, n_tests, n_failures, n_errors, n_seconds):
def totals(self, n_tests, n_failures, n_errors, n_seconds,
n_skipped=0):
"""Summarize the results of all layers."""
print(("Total: %s tests, %s failures, %s errors in %s."
% (n_tests, n_failures, n_errors,
self.format_seconds(n_seconds))))
print("Total: %s tests, %s failures, %s errors and %s skipped in %s."
% (n_tests, n_failures, n_errors, n_skipped,
self.format_seconds(n_seconds)))

def list_of_tests(self, tests, layer_name):
"""Report a list of test names."""
Expand Down Expand Up @@ -303,6 +306,22 @@ def test_success(self, test, seconds):
sys.stdout.write(s)
self.test_width += len(s) + 1

def test_skipped(self, test, reason):
"""Report that a test was skip.
Should be called right after start_test().
The next output operation should be stop_test().
"""
if self.verbose > 2:
s = " (skipped: %s)" % reason
elif self.verbose > 1:
s = " (skipped)"
else:
return
sys.stdout.write(s)
self.test_width += len(s) + 1

def test_error(self, test, seconds, exc_info):
"""Report that an error occurred while running a test.
Expand Down Expand Up @@ -436,7 +455,9 @@ class ColorfulOutputFormatter(OutputFormatter):
'actual-output': 'red',
'character-diffs': 'magenta',
'diff-chunk': 'magenta',
'exception': 'red'}
'exception': 'red',
'skipped': 'brightyellow',
}

# Map prefix character to color in diff output. This handles ndiff and
# udiff correctly, but not cdiff. In cdiff we ought to highlight '!' as
Expand Down Expand Up @@ -495,6 +516,31 @@ def error_count_color(self, n):
else:
return self.color('ok-number')

def skip_count_color(self, n):
"""Choose a color for the number of skipped tests."""
if n:
return self.color('skipped')
else:
return self.color('ok-number')

def test_skipped(self, test, reason):
"""Report that a test was skip.
Should be called right after start_test().
The next output operation should be stop_test().
"""
if self.verbose > 2:
s = " (%sskipped: %s%s)" % (
self.color('skipped'), reason, self.color('info'))
elif self.verbose > 1:
s = " (%sskipped%s)" % (
self.color('skipped'), self.color('info'))
else:
return
sys.stdout.write(s)
self.test_width += len(s) + 1

def info(self, message):
"""Print an informative message."""
print(self.colorize('info', message))
Expand Down Expand Up @@ -545,20 +591,25 @@ def format_seconds_short(self, n_seconds):
color = 'number'
return self.colorize(color, "%.3f s" % n_seconds)

def summary(self, n_tests, n_failures, n_errors, n_seconds):
def summary(self, n_tests, n_failures, n_errors, n_seconds,
n_skipped=0):
"""Summarize the results."""
sys.stdout.writelines([
self.color('info'), ' Ran ',
self.color('number'), str(n_tests),
self.color('info'), ' tests with ',
self.error_count_color(n_failures), str(n_failures),
self.color('info'), ' failures and ',
self.color('info'), ' failures, ',
self.error_count_color(n_errors), str(n_errors),
self.color('info'), ' errors in ',
self.color('info'), ' errors, ',
self.skip_count_color(n_skipped), str(n_skipped),
self.color('info'), ' skipped in ',
self.format_seconds(n_seconds, 'info'), '.',
self.color('normal'), '\n'])
self.color('normal'), '\n',
])

def totals(self, n_tests, n_failures, n_errors, n_seconds):
def totals(self, n_tests, n_failures, n_errors, n_seconds,
n_skipped=0):
"""Report totals (number of tests, failures, and errors)."""
sys.stdout.writelines([
self.color('info'), 'Total: ',
Expand All @@ -567,7 +618,9 @@ def totals(self, n_tests, n_failures, n_errors, n_seconds):
self.error_count_color(n_failures), str(n_failures),
self.color('info'), ' failures, ',
self.error_count_color(n_errors), str(n_errors),
self.color('info'), ' errors in ',
self.color('info'), ' errors, ',
self.error_count_color(n_skipped), str(n_skipped),
self.color('info'), ' skipped in ',
self.format_seconds(n_seconds, 'info'), '.',
self.color('normal'), '\n'])

Expand Down Expand Up @@ -868,7 +921,8 @@ def tear_down_not_supported(self):
self._subunit.addSkip(
FakeTest('%s:tearDown' % (layer_name,)), "tearDown not supported")

def summary(self, n_tests, n_failures, n_errors, n_seconds):
def summary(self, n_tests, n_failures, n_errors, n_seconds,
n_skipped=0):
"""Print out a summary.
Since subunit is a stream protocol format, it has no need for a
Expand Down Expand Up @@ -994,7 +1048,7 @@ def tests_with_failures(self, failures):
"""
pass

def totals(self, n_tests, n_failures, n_errors, n_seconds):
def totals(self, n_tests, n_failures, n_errors, n_seconds, n_skipped=0):
"""Summarize the results of all layers.
Simply not supported by the subunit formatter. Fancy summary output
Expand Down
37 changes: 26 additions & 11 deletions src/zope/testrunner/runner.py
Expand Up @@ -23,7 +23,10 @@
import threading
import time
import traceback
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest

from six import StringIO
from zope.testrunner.find import import_name
Expand Down Expand Up @@ -104,6 +107,7 @@ def __init__(self, defaults=None, args=None, found_suites=None,
self.failed = True

self.ran = 0
self.skipped = []
self.failures = []
self.errors = []

Expand Down Expand Up @@ -231,7 +235,8 @@ def run_tests(self):
feature.layer_setup(layer)
try:
self.ran += run_layer(self.options, layer_name, layer, tests,
setup_layers, self.failures, self.errors)
setup_layers, self.failures, self.errors,
self.skipped)
except zope.testrunner.interfaces.EndRun:
self.failed = True
return
Expand All @@ -249,7 +254,7 @@ def run_tests(self):
if layers_to_run:
self.ran += resume_tests(
self.script_parts, self.options, self.features,
layers_to_run, self.failures, self.errors)
layers_to_run, self.failures, self.errors, self.skipped)

if setup_layers:
if self.options.resume_layer is None:
Expand All @@ -259,7 +264,7 @@ def run_tests(self):
self.failed = bool(self.import_errors or self.failures or self.errors)


def run_tests(options, tests, name, failures, errors):
def run_tests(options, tests, name, failures, errors, skipped):
repeat = options.repeat or 1
repeat_range = iter(range(repeat))
ran = 0
Expand Down Expand Up @@ -331,9 +336,14 @@ def run_tests(options, tests, name, failures, errors):
# Python versions prior to 2.7 do not have the concept of
# unexpectedSuccesses.
failures.extend(result.unexpectedSuccesses)
if not hasattr(result, 'skipped'):
# Only in Python >= 2.7, Python >= 3.1, and when using unittest2
result.skipped = []
skipped.extend(result.skipped)
errors.extend(result.errors)
output.summary(result.testsRun, len(failures),
len(result.errors), t)
output.summary(result.testsRun,
len(failures), len(result.errors),
t, len(result.skipped))
ran = result.testsRun

if is_jython:
Expand Down Expand Up @@ -368,7 +378,7 @@ def run_tests(options, tests, name, failures, errors):


def run_layer(options, layer_name, layer, tests, setup_layers,
failures, errors):
failures, errors, skipped):

output = options.output
gathered = []
Expand All @@ -392,7 +402,7 @@ def run_layer(options, layer_name, layer, tests, setup_layers,
errors.append((SetUpLayerFailure(layer), sys.exc_info()))
return 0
else:
return run_tests(options, tests, layer_name, failures, errors)
return run_tests(options, tests, layer_name, failures, errors, skipped)


class SetUpLayerFailure(unittest.TestCase):
Expand All @@ -410,7 +420,7 @@ def __str__(self):


def spawn_layer_in_subprocess(result, script_parts, options, features,
layer_name, layer, failures, errors,
layer_name, layer, failures, errors, skipped,
resume_number):
output = options.output

Expand Down Expand Up @@ -564,7 +574,8 @@ def write(self, out):
self.stdout.append(out)


def resume_tests(script_parts, options, features, layers, failures, errors):
def resume_tests(script_parts, options, features, layers, failures, errors,
skipped):
results = []
stdout_queue = None
if options.processes == 1:
Expand All @@ -582,7 +593,7 @@ def resume_tests(script_parts, options, features, layers, failures, errors):
ready_threads.append(threading.Thread(
target=spawn_layer_in_subprocess,
args=(result, script_parts, options, features, layer_name, layer,
failures, errors, resume_number)))
failures, errors, skipped, resume_number)))
resume_number += 1

# Now start a few threads at a time.
Expand Down Expand Up @@ -747,6 +758,10 @@ def addSuccess(self, test):
t = max(time.time() - self._start_time, 0.0)
self.options.output.test_success(test, t)

def addSkip(self, test, reason):
unittest.TestResult.addSkip(self, test, reason)
self.options.output.test_skipped(test, reason)

def addError(self, test, exc_info):
self.options.output.test_error(test, time.time() - self._start_time,
exc_info)
Expand Down
2 changes: 1 addition & 1 deletion src/zope/testrunner/statistics.py
Expand Up @@ -43,4 +43,4 @@ def report(self):
return
self.runner.options.output.totals(
self.runner.ran, len(self.runner.failures), len(self.runner.errors),
self.total_time)
self.total_time, len(self.runner.skipped))
15 changes: 15 additions & 0 deletions src/zope/testrunner/tests/test_doctest.py
Expand Up @@ -291,6 +291,21 @@ def test_suite():
)
)

skip_feature = True
if sys.version_info < (2, 7, 0):
try:
import unittest2
except ImportError:
skip_feature = False

if skip_feature:
suites.append(
doctest.DocFileSuite(
'testrunner-report-skipped.txt',
setUp=setUp, tearDown=tearDown,
optionflags=doctest.ELLIPSIS+doctest.NORMALIZE_WHITESPACE,
checker=checker)
)

if hasattr(sys, 'gettotalrefcount'):
suites.append(
Expand Down
2 changes: 1 addition & 1 deletion src/zope/testrunner/tests/testrunner-arguments.txt
Expand Up @@ -18,7 +18,7 @@ explicitly.
Set up samplelayers.Layer1 in N.NNN seconds.
Set up samplelayers.Layer11 in N.NNN seconds.
Set up samplelayers.Layer111 in N.NNN seconds.
Ran 26 tests with 0 failures and 0 errors in N.NNN seconds.
Ran 26 tests with 0 failures, 0 errors and 0 skipped in N.NNN seconds.
Tearing down left over layers:
Tear down samplelayers.Layer111 in N.NNN seconds.
Tear down samplelayers.Layerx in N.NNN seconds.
Expand Down

0 comments on commit c9a45e3

Please sign in to comment.