1# coding: utf-8 2from __future__ import unicode_literals, division, absolute_import, print_function 3 4import unittest 5import re 6import sys 7import warnings 8 9from . import requires_oscrypto 10from ._import import _preload 11 12from tests import test_classes 13 14if sys.version_info < (3,): 15 range = xrange # noqa 16 from cStringIO import StringIO 17else: 18 from io import StringIO 19 20 21run_args = [ 22 { 23 'name': 'regex', 24 'kwarg': 'matcher', 25 }, 26 { 27 'name': 'repeat_count', 28 'kwarg': 'repeat', 29 'cast': 'int', 30 }, 31] 32 33 34def run(matcher=None, repeat=1, ci=False): 35 """ 36 Runs the tests 37 38 :param matcher: 39 A unicode string containing a regular expression to use to filter test 40 names by. A value of None will cause no filtering. 41 42 :param repeat: 43 An integer - the number of times to run the tests 44 45 :param ci: 46 A bool, indicating if the tests are being run as part of CI 47 48 :return: 49 A bool - if the tests succeeded 50 """ 51 52 _preload(requires_oscrypto, not ci) 53 54 warnings.filterwarnings("error") 55 56 loader = unittest.TestLoader() 57 # We have to manually track the list of applicable tests because for 58 # some reason with Python 3.4 on Windows, the tests in a suite are replaced 59 # with None after being executed. This breaks the repeat functionality. 60 test_list = [] 61 for test_class in test_classes(): 62 if matcher: 63 names = loader.getTestCaseNames(test_class) 64 for name in names: 65 if re.search(matcher, name): 66 test_list.append(test_class(name)) 67 else: 68 test_list.append(loader.loadTestsFromTestCase(test_class)) 69 70 stream = sys.stdout 71 verbosity = 1 72 if matcher and repeat == 1: 73 verbosity = 2 74 elif repeat > 1: 75 stream = StringIO() 76 77 for _ in range(0, repeat): 78 suite = unittest.TestSuite() 79 for test in test_list: 80 suite.addTest(test) 81 result = unittest.TextTestRunner(stream=stream, verbosity=verbosity).run(suite) 82 83 if len(result.errors) > 0 or len(result.failures) > 0: 84 if repeat > 1: 85 print(stream.getvalue()) 86 return False 87 88 if repeat > 1: 89 stream.truncate(0) 90 91 return True 92