|
import sys |
|
import time |
|
import os |
|
import os.path as op |
|
from argparse import ArgumentParser, RawDescriptionHelpFormatter |
|
|
|
import sfepy |
|
if sfepy.top_dir not in sys.path: sys.path.append(sfepy.top_dir) |
|
|
|
from sfepy.base.conf import ProblemConf, get_standard_keywords |
|
|
|
class OutputFilter(object): |
|
|
|
def __init__(self, allowed_lines): |
|
self.allowed_lines = allowed_lines |
|
self.msg_type1 = ['...', '!!!', '+++', '---'] |
|
self.msg_type2 = ['<<<', '>>>'] |
|
self.start() |
|
|
|
def start(self): |
|
self.stdout = sys.stdout |
|
sys.stdout = self |
|
|
|
def write(self, msg): |
|
if self.stdout is not None: |
|
msg_type = msg[:3] |
|
if msg_type in self.allowed_lines: |
|
if msg_type in self.msg_type1: |
|
msg = ''.join((msg[:3], ' ', msg[3:])) |
|
elif msg_type in self.msg_type2: |
|
msg = msg[4:] |
|
self.stdout.write(msg) |
|
self.stdout.write('\n') |
|
|
|
def flush(self): |
|
self.stdout.flush() |
|
|
|
def stop(self): |
|
sys.stdout = self.stdout |
|
self.stdout = None |
|
|
|
def run_test(conf_name, options): |
|
try: |
|
os.makedirs(options.out_dir) |
|
except OSError as e: |
|
if e.errno != 17: # [Errno 17] File exists |
|
raise |
|
|
|
if options.filter_none or options.debug: |
|
of = None |
|
elif options.filter_less: |
|
of = OutputFilter(['<<<', '>>>', '...', '!!!', '+++', '---']) |
|
elif options.filter_more: |
|
of = OutputFilter(['+++', '---']) |
|
else: |
|
of = OutputFilter(['<<<', '+++', '---']) |
|
|
|
print('<<< %s' % conf_name) |
|
|
|
_required, other = get_standard_keywords() |
|
required = ['Test'] |
|
|
|
num = 1 |
|
test_time = 0.0 |
|
try: |
|
conf = ProblemConf.from_file(conf_name, required, _required + other) |
|
test = conf.funmod.Test.from_conf(conf, options) |
|
num = test.get_number() |
|
ok = True |
|
print('>>> test instance prepared (%d test(s))' % num) |
|
except KeyboardInterrupt: |
|
print('>>> interrupted') |
|
sys.exit(0) |
|
except: |
|
print('--- test instance creation failed') |
|
if options.debug: |
|
raise |
|
ok, n_fail, n_total = False, num, num |
|
|
|
if ok: |
|
try: |
|
tt = time.clock() |
|
ok, n_fail, n_total = test.run(options.debug) |
|
test_time = time.clock() - tt |
|
except KeyboardInterrupt: |
|
print('>>> interrupted') |
|
sys.exit(0) |
|
except Exception as e: |
|
print('>>> %s' % e.__class__) |
|
if options.debug: |
|
raise |
|
ok, n_fail, n_total = False, num, num |
|
|
|
if ok: |
|
print('>>> all passed in %.2f s' % test_time) |
|
else: |
|
print('!!! %s test failed' % n_fail) |
|
|
|
if of is not None: |
|
of.stop() |
|
|
|
return n_fail, n_total, test_time |
|
|
|
def wrap_run_tests(options): |
|
def run_tests(stats, dir_name, filenames): |
|
filenames = [filename for filename in sorted(filenames) |
|
if (len(filename) > 8) and |
|
filename[:5] == 'test_' and filename[-3:] == '.py'] |
|
|
|
print('<<< directory: %s, test files: %d' % (dir_name, len(filenames))) |
|
|
|
for filename in filenames: |
|
conf_name = op.join(dir_name, filename) |
|
|
|
n_fail, n_total, test_time = run_test(conf_name, options) |
|
|
|
stats[0] += 1 |
|
stats[1] += n_fail |
|
stats[2] += n_total |
|
stats[3] += test_time |
|
|
|
return run_tests |
|
|
|
def get_dir(default): |
|
if sfepy.in_source_tree: |
|
out = default |
|
else: |
|
out = op.normpath(op.join(sfepy.data_dir, default)) |
|
return out |
|
|
|
help = { |
|
'dir' : 'directory with tests [default: %(default)s]', |
|
'out_dir' : 'directory for storing test results and temporary files' |
|
' [default: %(default)s]', |
|
'debug' : 'raise silenced exceptions to see what was wrong', |
|
'filter-none' : 'do not filter any messages', |
|
'filter-less' : 'filter output (suppress all except test messages)', |
|
'filter-more' : 'filter output (suppress all except test result messages)', |
|
'print-doc' : 'print the docstring of this file (howto write new tests)', |
|
} |
|
|
|
def main(): |
|
parser = ArgumentParser(description=__doc__, |
|
formatter_class=RawDescriptionHelpFormatter |
|
) |
|
parser.add_argument("-v", "--version", action="version", |
|
version="%(prog)s " + sfepy.__version__) |
|
parser.add_argument("--print-doc", |
|
action="store_true", dest="print_doc", |
|
default=False, help=help['print-doc']) |
|
parser.add_argument("-d", "--dir", metavar='directory', |
|
action="store", dest="test_dir", |
|
default=get_dir('tests'), |
|
help=help['dir']) |
|
parser.add_argument("-o", "--output", metavar='directory', |
|
action="store", dest="out_dir", |
|
default=get_dir('output-tests'), |
|
help=help['out_dir']) |
|
parser.add_argument("--debug", |
|
action="store_true", dest="debug", |
|
default=False, help=help['debug']) |
|
parser.add_argument("--filter-none", |
|
action="store_true", dest="filter_none", |
|
default=False, help=help['filter-none']) |
|
parser.add_argument("--filter-less", |
|
action="store_true", dest="filter_less", |
|
default=False, help=help['filter-less']) |
|
parser.add_argument("--filter-more", |
|
action="store_true", dest="filter_more", |
|
default=False, help=help['filter-more']) |
|
parser.add_argument("test_filename", nargs="*", default=[]) |
|
|
|
options = parser.parse_args() |
|
|
|
if options.print_doc: |
|
print(__doc__) |
|
return |
|
|
|
run_tests = wrap_run_tests(options) |
|
stats = [0, 0, 0, 0.0] |
|
|
|
if len(options.test_filename) > 0: |
|
for test_filename in options.test_filename: |
|
dirname, filename = op.split(test_filename) |
|
run_tests(stats, dirname, [filename]) |
|
else: |
|
for dirpath, dirnames, filenames in os.walk(options.test_dir): |
|
run_tests(stats, dirpath, filenames) |
|
|
|
print('%d test file(s) executed in %.2f s, %d failure(s) of %d test(s)' |
|
% (stats[0], stats[3], stats[1], stats[2])) |
|
|
|
return stats[1] |
|
|
|
if __name__ == '__main__': |
|
sys.exit(main()) |