# coding: utf-8 # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """TestRunner and TestResult for gabbi-run.""" from unittest import TestResult from unittest import TextTestResult from unittest import TextTestRunner import pytest from gabbi import utils class ConciseTestResult(TextTestResult): """A TextTestResult with simple but useful output. If the output is a tty or GABBI_FORCE_COLOR is set in the environment, output will be colorized. """ def __init__(self, stream, descriptions, verbosity): super(ConciseTestResult, self).__init__( stream, descriptions, verbosity) self.colorize = utils.get_colorizer(stream) def startTest(self, test): super(TextTestResult, self).startTest(test) if self.showAll: self.stream.write('... ') self.stream.flush() def addSuccess(self, test): super(TextTestResult, self).addSuccess(test) if self.showAll: self.stream.write(self.colorize('GREEN', '✓ ')) self.stream.writeln(self.getDescription(test)) def addFailure(self, test, err): super(TextTestResult, self).addFailure(test, err) if self.showAll: self.stream.write(self.colorize('RED', '✗ ')) self.stream.writeln(self.getDescription(test)) def addError(self, test, err): super(TextTestResult, self).addError(test, err) if self.showAll: self.stream.write(self.colorize('RED', 'E ')) self.stream.writeln(self.getDescription(test)) def addSkip(self, test, reason): super(TextTestResult, self).addSkip(test, reason) if self.showAll: self.stream.write('- ') self.stream.writeln(self.getDescription(test)) self.stream.writeln('\t[skipped] {0!r}'.format(reason)) def addExpectedFailure(self, test, err): super(TextTestResult, self).addExpectedFailure(test, err) if self.showAll: self.stream.write('o ') self.stream.writeln(self.getDescription(test)) self.stream.writeln('\t[expected failure]') def addUnexpectedSuccess(self, test): super(TextTestResult, self).addUnexpectedSuccess(test) if self.showAll: self.stream.write('! ') self.stream.writeln(self.getDescription(test)) self.stream.writeln('\t[unexpected success]') def getDescription(self, test): # Chop the test method ('test_request') off the test.id(). name = test.id().rsplit('.', 1)[0] desc = test.test_data.get('desc', None) return ': '.join((name, desc)) if desc else name def _exc_info_to_string(self, err, test): """Override exception to string handling The default does too much. We don't want doctoring. We want information! """ return err def printErrorList(self, flavor, errors): for test, err in errors: # err[0] is the type of exception # err[1] is the args of the exception # err[3] is the traceback, not currently used self.stream.writeln('%s: %s' % (flavor, self.getDescription(test))) message = str(err[1]) for line in message.splitlines(): self.stream.writeln('\t%s' % line) class PyTestResult(TestResult): """Wrap a test result to allow it to work with pytest. The main behaviors here are: * to turn what had been exceptions back into exceptions * use pytest's skip and xfail methods """ def addFailure(self, test, err): raise err[1] def addError(self, test, err): raise err[1] def addSkip(self, test, reason): pytest.skip(reason) def addExpectedFailure(self, test, err): pytest.xfail('%s' % err[1]) class ConciseTestRunner(TextTestRunner): """A TextTestRunner that uses ConciseTestResult for reporting results.""" resultclass = ConciseTestResult