mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Improvement TW-1255
- #TW-1255 New testing framework (thanks to Renato Alves). Signed-off-by: Paul Beckingham <paul@beckingham.net>
This commit is contained in:
parent
d83f90f82b
commit
112d4bfb14
4 changed files with 145 additions and 100 deletions
|
@ -7,6 +7,7 @@ Features
|
|||
+ #1501 info report streamlining - partially implemented.
|
||||
+ #TW-255 'Mask' instead of 'iMask' shown in info report (thanks to Benjamin
|
||||
Weber)
|
||||
+ #TW-1255 New testing framework (thanks to Renato Alves).
|
||||
+ Removed deprecated 'echo.command' setting, in favor of the 'header' and
|
||||
'affected' verbosity tokens.
|
||||
+ Removed deprecated 'edit.verbose' setting, in favor of the 'edit' verbosity
|
||||
|
|
134
test/simpletap/__init__.py
Normal file
134
test/simpletap/__init__.py
Normal file
|
@ -0,0 +1,134 @@
|
|||
################################################################################
|
||||
## taskwarrior - a command line task list manager.
|
||||
##
|
||||
## Copyright 2006-2014, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
# Original version by Renato Alves
|
||||
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
|
||||
class TAPTestResult(unittest.result.TestResult):
|
||||
def __init__(self, stream, descriptions, verbosity):
|
||||
super(TAPTestResult, self).__init__(stream, descriptions, verbosity)
|
||||
self.stream = stream
|
||||
self.descriptions = descriptions
|
||||
self.verbosity = verbosity
|
||||
|
||||
def getDescription(self, test):
|
||||
doc_first_line = test.shortDescription()
|
||||
if self.descriptions and doc_first_line:
|
||||
return doc_first_line
|
||||
else:
|
||||
return str(test)
|
||||
|
||||
def startTestRun(self, total="unk"):
|
||||
self.stream.writeln("1..{0}".format(total))
|
||||
|
||||
def report(self, test, status=None, err=None):
|
||||
desc = self.getDescription(test)
|
||||
try:
|
||||
exception, msg, _ = err
|
||||
except (TypeError, ValueError):
|
||||
exception = ""
|
||||
msg = err
|
||||
else:
|
||||
exception = exception.__name__
|
||||
msg = str(msg)
|
||||
|
||||
if status:
|
||||
if status == "SKIP":
|
||||
self.stream.writeln("skip {0} - {1}".format(self.testsRun,
|
||||
desc))
|
||||
else:
|
||||
self.stream.writeln("not ok {0} - {1}".format(self.testsRun,
|
||||
desc))
|
||||
self.stream.writeln("# {0}: {1}".format(status, exception))
|
||||
padding = " " * (len(status) + 3)
|
||||
for line in msg.splitlines():
|
||||
self.stream.writeln("#{0}{1}".format(padding, line))
|
||||
else:
|
||||
self.stream.writeln("ok {0} - {1}".format(self.testsRun, desc))
|
||||
|
||||
self.stream.flush()
|
||||
|
||||
def addSuccess(self, test):
|
||||
super(TAPTestResult, self).addSuccess(test)
|
||||
self.report(test)
|
||||
|
||||
def addError(self, test, err):
|
||||
super(TAPTestResult, self).addError(test, err)
|
||||
self.report(test, "ERROR", err)
|
||||
|
||||
def addFailure(self, test, err):
|
||||
super(TAPTestResult, self).addFailure(test, err)
|
||||
self.report(test, "FAIL", err)
|
||||
|
||||
def addSkip(self, test, reason):
|
||||
super(TAPTestResult, self).addSkip(test, reason)
|
||||
self.report(test, "SKIP", reason)
|
||||
|
||||
|
||||
class TAPTestRunner(unittest.runner.TextTestRunner):
|
||||
"""A test runner that displays results using the Test Anything Protocol
|
||||
syntax.
|
||||
|
||||
Inherits from TextTestRunner the default runner.
|
||||
"""
|
||||
resultclass = TAPTestResult
|
||||
|
||||
def run(self, test):
|
||||
result = self._makeResult()
|
||||
unittest.signals.registerResult(result)
|
||||
result.failfast = self.failfast
|
||||
result.buffer = self.buffer
|
||||
|
||||
with warnings.catch_warnings():
|
||||
if getattr(self, "warnings", None):
|
||||
# if self.warnings is set, use it to filter all the warnings
|
||||
warnings.simplefilter(self.warnings)
|
||||
# if the filter is 'default' or 'always', special-case the
|
||||
# warnings from the deprecated unittest methods to show them
|
||||
# no more than once per module, because they can be fairly
|
||||
# noisy. The -Wd and -Wa flags can be used to bypass this
|
||||
# only when self.warnings is None.
|
||||
if self.warnings in ['default', 'always']:
|
||||
warnings.filterwarnings('module',
|
||||
category=DeprecationWarning,
|
||||
message='Please use assert\w+ instead.')
|
||||
startTestRun = getattr(result, 'startTestRun', None)
|
||||
if startTestRun is not None:
|
||||
startTestRun(test.countTestCases())
|
||||
try:
|
||||
test(result)
|
||||
finally:
|
||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||
if stopTestRun is not None:
|
||||
stopTestRun()
|
||||
|
||||
return result
|
|
@ -1,98 +0,0 @@
|
|||
#
|
||||
# Code from https://github.com/vit1251/unittest-tap-reporting
|
||||
# No explicit license
|
||||
#
|
||||
# With modifications by Renato Alves
|
||||
#
|
||||
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
|
||||
|
||||
class TAPTestResult(unittest.result.TestResult):
|
||||
version = 13
|
||||
|
||||
def __init__(self, stream=None, descriptions=None, plan=None):
|
||||
super(TAPTestResult, self).__init__()
|
||||
#self.stream = sys.stdout
|
||||
self.stream = stream
|
||||
self._current = 0
|
||||
self.descriptions = descriptions
|
||||
#self.stream.write("TAP version %d\n" % (self.version, ))
|
||||
self.stream.write("%d..%d\n" % (1, plan, ))
|
||||
|
||||
def getDescription(self, test):
|
||||
doc_first_line = test.shortDescription()
|
||||
if self.descriptions and doc_first_line:
|
||||
return doc_first_line
|
||||
#return ' - '.join((str(test), doc_first_line))
|
||||
else:
|
||||
return str(test)
|
||||
|
||||
def addSuccess(self, test):
|
||||
#super(TAPTestResult, self).addSuccess(test)
|
||||
#print test
|
||||
self.stream.write("ok %d - %s\n" % (self._current+1, self.getDescription(test)))
|
||||
self.stream.flush()
|
||||
self._current += 1
|
||||
|
||||
def addError(self, test, err):
|
||||
(exctype, value, tb) = err
|
||||
self.stream.write("not ok %d - %s\n# ERROR: %s\n" % (self._current+1, self.getDescription(test), value))
|
||||
self.stream.flush()
|
||||
self._current += 1
|
||||
|
||||
def addFailure(self, test, err):
|
||||
(exctype, value, tb) = err
|
||||
self.stream.write("not ok %d - %s\n# FAIL: %s\n" % (self._current+1, self.getDescription(test), value))
|
||||
self.stream.flush()
|
||||
self._current += 1
|
||||
|
||||
def addSkip(self, test, reason):
|
||||
self.stream.write("not ok %d - %s # SKIP: %s\n" % (self._current+1, self.getDescription(test), reason))
|
||||
self.stream.flush()
|
||||
self._current += 1
|
||||
|
||||
|
||||
class TAPTestRunner(object):
|
||||
"""A test runner ia abstract class that displays results in user defined form.
|
||||
|
||||
It prints out the names of tests as they are run, errors as they
|
||||
occur, and a summary of the results at the end of the test run.
|
||||
"""
|
||||
resultclass = TAPTestResult
|
||||
|
||||
def __init__(self, stream=sys.stderr, descriptions=True, plan=None, failfast=False, buffer=False, resultclass=None):
|
||||
self.stream = stream
|
||||
self.descriptions = descriptions
|
||||
self.plan = plan
|
||||
self.failfast = failfast
|
||||
self.buffer = buffer
|
||||
if resultclass is not None:
|
||||
self.resultclass = resultclass
|
||||
|
||||
def _makeResult(self, test):
|
||||
if self.plan is None:
|
||||
self.plan = test.countTestCases()
|
||||
return self.resultclass(self.stream, self.descriptions, self.plan)
|
||||
|
||||
def run(self, test):
|
||||
"Run the given test case or test suite."
|
||||
result = self._makeResult(test=test)
|
||||
#registerResult(result)
|
||||
result.failfast = self.failfast
|
||||
result.buffer = self.buffer
|
||||
startTime = time.time()
|
||||
startTestRun = getattr(result, 'startTestRun', None)
|
||||
if startTestRun is not None:
|
||||
startTestRun()
|
||||
try:
|
||||
test(result)
|
||||
finally:
|
||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||
if stopTestRun is not None:
|
||||
stopTestRun()
|
||||
stopTime = time.time()
|
||||
timeTaken = stopTime - startTime
|
||||
return result
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
|
@ -43,6 +43,14 @@ class TestVersion(unittest.TestCase):
|
|||
expected = "Copyright \(C\) \d{4} - %d" % (datetime.now().year - 1,)
|
||||
self.assertRegexpMatches(out.decode("utf8"), expected)
|
||||
|
||||
def testFailOther(self):
|
||||
"""Nothing to do with Copyright"""
|
||||
self.assertEqual("I like to code", "I like\nto code\n")
|
||||
|
||||
@unittest.skipIf(1 != 0, "This machine has sane logic")
|
||||
def testSkipped(self):
|
||||
"""Test all logic of the world"""
|
||||
|
||||
def tearDown(self):
|
||||
"""Executed after each test in the class"""
|
||||
|
||||
|
@ -53,7 +61,7 @@ class TestVersion(unittest.TestCase):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from taprunner import TAPTestRunner
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue